Skip to content

Commit

Permalink
Merge docrails
Browse files Browse the repository at this point in the history
  • Loading branch information
lifo committed Mar 24, 2009
1 parent 6ed42eb commit f97832b
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 66 deletions.
35 changes: 21 additions & 14 deletions actionpack/lib/action_view/helpers/form_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -628,20 +628,23 @@ def text_area(object_name, method, options = {})
#
# The HTML specification says unchecked check boxes are not successful, and
# thus web browsers do not send them. Unfortunately this introduces a gotcha:
# if an Invoice model has a +paid+ flag, and in the form that edits a paid
# if an +Invoice+ model has a +paid+ flag, and in the form that edits a paid
# invoice the user unchecks its check box, no +paid+ parameter is sent. So,
# any mass-assignment idiom like
#
# @invoice.update_attributes(params[:invoice])
#
# wouldn't update the flag.
#
# To prevent this the helper generates a hidden field with the same name as
# the checkbox after the very check box. So, the client either sends only the
# hidden field (representing the check box is unchecked), or both fields.
# Since the HTML specification says key/value pairs have to be sent in the
# same order they appear in the form and Rails parameters extraction always
# gets the first occurrence of any given key, that works in ordinary forms.
# To prevent this the helper generates an auxiliary hidden field before
# the very check box. The hidden field has the same name and its
# attributes mimick an unchecked check box.
#
# This way, the client either sends only the hidden field (representing
# the check box is unchecked), or both fields. Since the HTML specification
# says key/value pairs have to be sent in the same order they appear in the
# form, and parameters extraction gets the last occurrence of any repeated
# key in the query string, that works for ordinary forms.
#
# Unfortunately that workaround does not work when the check box goes
# within an array-like parameter, as in
Expand All @@ -652,22 +655,26 @@ def text_area(object_name, method, options = {})
# <% end %>
#
# because parameter name repetition is precisely what Rails seeks to distinguish
# the elements of the array.
# the elements of the array. For each item with a checked check box you
# get an extra ghost item with only that attribute, assigned to "0".
#
# In that case it is preferable to either use +check_box_tag+ or to use
# hashes instead of arrays.
#
# ==== Examples
# # Let's say that @post.validated? is 1:
# check_box("post", "validated")
# # => <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
# # <input name="post[validated]" type="hidden" value="0" />
# # => <input name="post[validated]" type="hidden" value="0" />
# # <input type="checkbox" id="post_validated" name="post[validated]" value="1" />
#
# # Let's say that @puppy.gooddog is "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" />
# # => <input name="puppy[gooddog]" type="hidden" value="no" />
# # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
#
# check_box("eula", "accepted", { :class => 'eula_check' }, "yes", "no")
# # => <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
# # <input name="eula[accepted]" type="hidden" value="no" />
# # => <input name="eula[accepted]" type="hidden" value="no" />
# # <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
#
def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
InstanceTag.new(object_name, method, self, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value)
Expand Down
6 changes: 3 additions & 3 deletions actionpack/lib/action_view/helpers/text_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def simple_format(text, html_options={})

# Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
# will limit what should be linked. You can add HTML attributes to the links using
# <tt>:href_options</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
# <tt>:html</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
# e-mail address is yielded and the result is used as the link text.
#
Expand All @@ -341,7 +341,7 @@ def simple_format(text, html_options={})
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :href_options => { :target => '_blank' }) do |text|
# auto_link(post_body, :html => { :target => '_blank' }) do |text|
# truncate(text, 15)
# end
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
Expand All @@ -359,7 +359,7 @@ def simple_format(text, html_options={})
# auto_link(post_body, :all, :target => "_blank") # => Once upon\na time
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.myblog.com</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
def auto_link(text, *args, &block)#link = :all, href_options = {}, &block)
def auto_link(text, *args, &block)#link = :all, html = {}, &block)
return '' if text.blank?

options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
Expand Down
23 changes: 13 additions & 10 deletions activerecord/lib/active_record/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -810,25 +810,28 @@ def destroy(id)

# Updates all records with details given if they match a set of conditions supplied, limits and order can
# also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
# database. It does not instantiate the involved models and it does not trigger Active Record callbacks.
# database. It does not instantiate the involved models and it does not trigger Active Record callbacks
# or validations.
#
# ==== Parameters
#
# * +updates+ - A string of column and value pairs that will be set on any records that match conditions. This creates the SET clause of the generated SQL.
# * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro for more info.
# * +updates+ - A string, array, or hash representing the SET part of an SQL statement.
# * +conditions+ - A string, array, or hash representing the WHERE part of an SQL statement. See conditions in the intro.
# * +options+ - Additional options are <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
#
# ==== Examples
#
# # Update all billing objects with the 3 different attributes given
# Billing.update_all( "category = 'authorized', approved = 1, author = 'David'" )
# # Update all customers with the given attributes
# Customer.update_all :wants_email => true
#
# # Update records that match our conditions
# Billing.update_all( "author = 'David'", "title LIKE '%Rails%'" )
# # Update all books with 'Rails' in their title
# Book.update_all "author = 'David'", "title LIKE '%Rails%'"
#
# # Update records that match our conditions but limit it to 5 ordered by date
# Billing.update_all( "author = 'David'", "title LIKE '%Rails%'",
# :order => 'created_at', :limit => 5 )
# # Update all avatars migrated more than a week ago
# Avatar.update_all ['migrated_at = ?, Time.now.utc], ['migrated_at > ?', 1.week.ago]
#
# # Update all books that match our conditions, but limit it to 5 ordered by date
# Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5
def update_all(updates, conditions = nil, options = {})
sql = "UPDATE #{quoted_table_name} SET #{sanitize_sql_for_assignment(updates)} "

Expand Down
14 changes: 7 additions & 7 deletions activeresource/README
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= Active Resource

Active Resource (ARes) connects business objects and Representational State Transfer (REST)
web services. It implements object-relational mapping for REST webservices to provide transparent
web services. It implements object-relational mapping for REST web services to provide transparent
proxying capabilities between a client (ActiveResource) and a RESTful service (which is provided by Simply RESTful routing
in ActionController::Resources).

Expand All @@ -22,14 +22,14 @@ received and serialized into a usable Ruby object.

=== Configuration and Usage

Putting ActiveResource to use is very similar to ActiveRecord. It's as simple as creating a model class
Putting Active Resource to use is very similar to Active Record. It's as simple as creating a model class
that inherits from ActiveResource::Base and providing a <tt>site</tt> class variable to it:

class Person < ActiveResource::Base
self.site = "http://api.people.com:3000/"
end

Now the Person class is REST enabled and can invoke REST services very similarly to how ActiveRecord invokes
Now the Person class is REST enabled and can invoke REST services very similarly to how Active Record invokes
lifecycle methods that operate against a persistent store.

# Find a person with id = 1
Expand All @@ -42,7 +42,7 @@ records. But rather than dealing directly with a database record, you're dealin
==== Protocol

Active Resource is built on a standard XML format for requesting and submitting resources over HTTP. It mirrors the RESTful routing
built into ActionController but will also work with any other REST service that properly implements the protocol.
built into Action Controller but will also work with any other REST service that properly implements the protocol.
REST uses HTTP, but unlike "typical" web applications, it makes use of all the verbs available in the HTTP specification:

* GET requests are used for finding and retrieving resources.
Expand All @@ -55,8 +55,8 @@ for more general information on REST web services, see the article here[http://e

==== Find

GET Http requests expect the XML form of whatever resource/resources is/are being requested. So,
for a request for a single element - the XML of that item is expected in response:
Find requests use the GET method and expect the XML form of whatever resource/resources is/are being requested. So,
for a request for a single element, the XML of that item is expected in response:

# Expects a response of
#
Expand Down Expand Up @@ -101,7 +101,7 @@ Collections can also be requested in a similar fashion

==== Create

Creating a new resource submits the xml form of the resource as the body of the request and expects
Creating a new resource submits the XML form of the resource as the body of the request and expects
a 'Location' header in the response with the RESTful URL location of the newly created resource. The
id of the newly created resource is parsed out of the Location response header and automatically set
as the id of the ARes object.
Expand Down
20 changes: 10 additions & 10 deletions activeresource/lib/active_resource/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module ActiveResource
# end
#
# Now the Person class is mapped to RESTful resources located at <tt>http://api.people.com:3000/people/</tt>, and
# you can now use Active Resource's lifecycles methods to manipulate resources. In the case where you already have
# you can now use Active Resource's lifecycle methods to manipulate resources. In the case where you already have
# an existing model with the same name as the desired RESTful resource you can set the +element_name+ value.
#
# class PersonResource < ActiveResource::Base
Expand Down Expand Up @@ -112,6 +112,7 @@ module ActiveResource
#
# Note: Some values cannot be provided in the URL passed to site. e.g. email addresses
# as usernames. In those situations you should use the separate user and password option.
#
# == Errors & Validation
#
# Error handling and validation is handled in much the same manner as you're used to seeing in
Expand Down Expand Up @@ -156,7 +157,7 @@ module ActiveResource
#
# === Validation errors
#
# Active Resource supports validations on resources and will return errors if any these validations fail
# Active Resource supports validations on resources and will return errors if any of these validations fail
# (e.g., "First name can not be blank" and so on). These types of errors are denoted in the response by
# a response code of <tt>422</tt> and an XML representation of the validation errors. The save operation will
# then fail (with a <tt>false</tt> return value) and the validation errors can be accessed on the resource in question.
Expand Down Expand Up @@ -413,7 +414,7 @@ def element_path(id, prefix_options = {}, query_options = nil)
# will split from the +prefix_options+.
#
# ==== Options
# * +prefix_options+ - A hash to add a prefix to the request for nested URL's (e.g., <tt>:account_id => 19</tt>
# * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
# would yield a URL like <tt>/accounts/19/purchases.xml</tt>).
# * +query_options+ - A hash to add items to the query string for the request.
#
Expand Down Expand Up @@ -691,7 +692,7 @@ def clone
end


# A method to determine if the resource a \new object (i.e., it has not been POSTed to the remote service yet).
# Returns +true+ if this object hasn't yet been saved, otherwise, returns +false+.
#
# ==== Examples
# not_new = Computer.create(:brand => 'Apple', :make => 'MacBook', :vendor => 'MacMall')
Expand Down Expand Up @@ -760,7 +761,7 @@ def hash
id.hash
end

# Duplicate the current resource without saving it.
# Duplicates the current resource without saving it.
#
# ==== Examples
# my_invoice = Invoice.create(:customer => 'That Company')
Expand All @@ -779,8 +780,8 @@ def dup
end
end

# A method to \save (+POST+) or \update (+PUT+) a resource. It delegates to +create+ if a \new object,
# +update+ if it is existing. If the response to the \save includes a body, it will be assumed that this body
# Saves (+POST+) or \updates (+PUT+) a resource. Delegates to +create+ if the object is \new,
# +update+ if it exists. If the response to the \save includes a body, it will be assumed that this body
# is XML for the final object as it looked after the \save (which would include attributes like +created_at+
# that weren't part of the original submit).
#
Expand Down Expand Up @@ -832,7 +833,7 @@ def exists?
!new? && self.class.exists?(to_param, :params => prefix_options)
end

# A method to convert the the resource to an XML string.
# Converts the resource to an XML string representation.
#
# ==== Options
# The +options+ parameter is handed off to the +to_xml+ method on each
Expand Down Expand Up @@ -861,8 +862,7 @@ def to_xml(options={})
attributes.to_xml({:root => self.class.element_name}.merge(options))
end

# Returns a JSON string representing the model. Some configuration is
# available through +options+.
# Converts the resource to a JSON string representation.
#
# ==== Options
# The +options+ are passed to the +to_json+ method on each
Expand Down
22 changes: 11 additions & 11 deletions activeresource/lib/active_resource/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,54 +95,54 @@ def site=(site)
@password = URI.decode(@site.password) if @site.password
end

# Set user for remote service.
# Sets the user for remote service.
def user=(user)
@user = user
end

# Set password for remote service.
# Sets the password for remote service.
def password=(password)
@password = password
end

# Set the number of seconds after which HTTP requests to the remote service should time out.
# Sets the number of seconds after which HTTP requests to the remote service should time out.
def timeout=(timeout)
@timeout = timeout
end

# Execute a GET request.
# Executes a GET request.
# Used to get (find) resources.
def get(path, headers = {})
format.decode(request(:get, path, build_request_headers(headers, :get)).body)
end

# Execute a DELETE request (see HTTP protocol documentation if unfamiliar).
# Executes a DELETE request (see HTTP protocol documentation if unfamiliar).
# Used to delete resources.
def delete(path, headers = {})
request(:delete, path, build_request_headers(headers, :delete))
end

# Execute a PUT request (see HTTP protocol documentation if unfamiliar).
# Executes a PUT request (see HTTP protocol documentation if unfamiliar).
# Used to update resources.
def put(path, body = '', headers = {})
request(:put, path, body.to_s, build_request_headers(headers, :put))
end

# Execute a POST request.
# Executes a POST request.
# Used to create new resources.
def post(path, body = '', headers = {})
request(:post, path, body.to_s, build_request_headers(headers, :post))
end

# Execute a HEAD request.
# Executes a HEAD request.
# Used to obtain meta-information about resources, such as whether they exist and their size (via response headers).
def head(path, headers = {})
request(:head, path, build_request_headers(headers))
end


private
# Makes request to remote service.
# Makes a request to the remote service.
def request(method, path, *arguments)
logger.info "#{method.to_s.upcase} #{site.scheme}://#{site.host}:#{site.port}#{path}" if logger
result = nil
Expand All @@ -153,7 +153,7 @@ def request(method, path, *arguments)
raise TimeoutError.new(e.message)
end

# Handles response and error codes from remote service.
# Handles response and error codes from the remote service.
def handle_response(response)
case response.code.to_i
when 301,302
Expand Down Expand Up @@ -183,7 +183,7 @@ def handle_response(response)
end
end

# Creates new Net::HTTP instance for communication with
# Creates new Net::HTTP instance for communication with the
# remote service and resources.
def http
http = Net::HTTP.new(@site.host, @site.port)
Expand Down
Loading

0 comments on commit f97832b

Please sign in to comment.