[ANN] Rails 0.8: Just shy of 100 additions, changes, tweaks, and fixes!

  • Thread starter David Heinemeier Hansson
  • Start date

D

David Heinemeier Hansson

It's been fifty days since our last confession, so it's no wonder that
this outpouring is by far the biggest yet in Rails history. It's
absolutely packed with goodies ranging from a whole new framework for
sending email to the smallest new alias for an existing method. In
total we're just shy of 100 additions, changes, tweaks, and fixes.

This is also the release with the highest number of contributors. I've
counted at least 23 different people with patches in Rails 0.8 -- and
there are many, many more responsible for suggestions and bug reports.
This is truely turning into a community movement and I'm extremely
pleased to be the steward for it.

Get it all from http://www.rubyonrails.org, talk it up on #rubyonrails
(FreeNet).

Or even easier, just do "gem install rails" (or "gem update" if you're
already running on Gem Rails) -- you'll automatically install all the
newest versions of the required dependencies. (NOTE: Wait 40 minutes
from this mail went out, so the gem repository is in synch -- couldn't
we check every 15 minutes instead of every hour :)?)

Commercial announcement: If you're looking for a place to host your
Rails project or just to play around with it online, we now have an
official hosting partner in TextDrive. I'm on board to ensure that the
Rails experience is top notch and in return 50% of the gross profits
are going to help further Rails. Read more on:
http://www.rubyonrails.org/show/TextDriveHosting


Rails 0.8.0: Multi-word classes are now welcome, WEBrick binding
================================================================

* Removed custom_table_name option for new_model now that the Inflector
is as powerful as it is

* Changed the default rake action to just do testing and separate API
generation and coding statistics into a "doc" task.

* Fixed WEBrick dispatcher to handle missing slashes in the URLs
gracefully [alexey]

* Added user option for all postgresql tool calls in the rakefile
[elvstone]

* Fixed problem with running "ruby public/dispatch.servlet" instead of
"cd public; ruby dispatch.servlet" [alexey]

* Fixed WEBrick server so that it no longer hardcodes the ruby
interpreter used to "ruby" but will get the one used based on the Ruby
runtime configuration. [Marcel Molina Jr.]

* Fixed Dispatcher so it'll route requests to magic_beans to
MagicBeansController/magic_beans_controller.rb [Caio Chassot]

* "new_controller MagicBeans" and "new_model SubscriptionPayments" will
now both behave properly as they use the new Inflector.

* Fixed problem with MySQL foreign key constraint checks in Rake
:clone_production_structure_to_test target [Andreas Schwarz]

* Changed WEBrick server to by default be auto-reloading, which is
slower but makes source changes instant. Class compilation cache can be
turned on with "-c" or "--cache-classes".

* Added "-b/--binding" option to WEBrick dispatcher to bind the server
to a specific IP address (default: 127.0.0.1) [Kevin Temp]

* dispatch.fcgi now DOESN'T set FCGI_PURE_RUBY as it was slowing things
down for now reason [Andreas Schwarz]

* Added new_mailer generator to work with Action Mailer

* Included new framework: Action Mailer 0.3

* Upgraded to Action Pack 0.9.0

* Upgraded to Active Record 1.0.0


Action Mailer 0.3: Easy email delivery and testing
==================================================

Action Mailer is framework for designing email-service layers. These
layers are used to consolidate code for sending out forgotten
passwords, welcoming wishes on signup, invoices for billing, and any
other use case that requires a written notification to either a person
or another system.

The framework works by setting up all the email details, except the
body, in methods on the service layer. Subject, recipients, sender, and
timestamp are all set up this way. An example of such a method:

def signed_up(recipient)
@recipients = recipient
@subject = "[Signed up] Welcome #{recipient}"
@from = "(e-mail address removed)"
@sent_on = Time.local(2004, 12, 12)

@body["recipient"] = recipient
end

The body of the email is created by using an Action View template
(regular ERb) that has the content of the @body hash available as
instance variables. So the corresponding body template for the method
above could look like this:

Hello there,

Mr. <%= @recipient %>

And if the recipient was given as "(e-mail address removed)", the email
generated would look like this:

Date: Sun, 12 Dec 2004 00:00:00 +0100
From: (e-mail address removed)
To: (e-mail address removed)
Subject: [Signed up] Welcome (e-mail address removed)

Hello there,

Mr. (e-mail address removed)

You never actually call the instance methods like signed_up directly.
Instead, you call class methods like deliver_* and create_* that are
automatically created for each instance method. So if the signed_up
method sat on ApplicationMailer, it would look like this:

ApplicationMailer.create_signed_up("(e-mail address removed)") # =>
tmail object for testing
ApplicationMailer.deliver_signed_up("(e-mail address removed)") # sends
the email
ApplicationMailer.new.signed_up("(e-mail address removed)") # won't
work!



Active Record 1.0.0: Easy email delivery and testing
====================================================


* Added OO-style associations methods [Florian Weber]. Examples:

Project#milestones_count => Project#milestones.size
Project#build_to_milestones => Project#milestones.build
Project#create_for_milestones => Project#milestones.create
Project#find_in_milestones => Project#milestones.find
Project#find_all_in_milestones => Project#milestones.find_all

* Added serialize as a new class method to control when text attributes
should be YAMLized or not. This means that automated serialization of
hashes, arrays, and so on WILL NO LONGER HAPPEN (#10). You need to do
something like this:

class User < ActiveRecord::Base
serialize :settings
end

This will assume that settings is a text column and will now YAMLize
any object put in that attribute. You can also specify an optional
:class_name option 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 :settings, :class_name => "Hash"
end

user = User.create("settings" => %w( one two three ))
User.find(user.id).settings # => raises SerializationTypeMismatch

* Added the option to connect to a different database for one model at
a time. Just call establish_connection on the class you want to have
connected to another database than Base. This will automatically also
connect decendents of that class to the different database [Renald
Buter].

* Added transactional protection for Base#save. Validations can now
check for values knowing that it happens in a transaction and callbacks
can raise exceptions knowing that the save will be rolled back.
[Suggested by Alexey Verkhovsky]

* Added column name quoting so reserved words, such as "references",
can be used as column names [Ryan Platte]

* Added the possibility to chain the return of what happened inside a
logged block [geech]:

This now works:
log { ... }.map { ... }

Instead of doing:
result = []
log { result = ... }
result.map { ... }

* Added "socket" option for the MySQL adapter, so you can change it to
something else than "/tmp/mysql.sock" [Anna Liss Cruz]

* Added respond_to? answers for all the attribute methods. So if Person
has a name attribute retrieved from the table schema,
person.respond_to? "name" will return true.

* Added Base.benchmark which can be used to aggregate logging and
benchmark, so you can measure and represent multiple statements in a
single block. Usage (hides all the SQL calls for the individual actions
and calculates total runtime for them all):

Project.benchmark("Creating project") do
project = Project.create("name" => "stuff")
project.create_manager("name" => "David")
project.milestones << Milestone.find_all
end

* Added logging of invalid SQL statements [Suggested by Daniel Von
Fange]

* Added alias Errors#[] for Errors#on, so you can now say
person.errors["name"] to retrieve the errors for name [Andreas Schwarz]

* Added RubyGems require attempt if sqlite-ruby is not available
through regular methods.

* Added compatibility with 2.x series of sqlite-ruby drivers. [Jamis
Buck]

* Added type safety for association assignments, so a
ActiveRecord::AssociationTypeMismatch will be raised if you attempt to
assign an object that's not of the associated class. This cures the
problem with nil giving id = 4 and fixnums giving id = 1 on mistaken
association assignments. [Reported by Andreas Schwarz]

* Added the option to keep many fixtures in one single YAML document
[what-a-day]

* Added the class method "inheritance_column" that can be overwritten
to return the name of an alternative column than "type" for storing the
type for inheritance hierarchies. [Dave Steinberg]

* Added [] and []= as an alternative way to access attributes when the
regular methods have been overwritten [Dave Steinberg]

* Added the option to observer more than one class at the time by
specifying observed_class as an array

* Added auto-id propagation support for tables with arbitrary primary
keys that have autogenerated sequences associated with them on
PostgreSQL. [Dave Steinberg]

* Changed that integer and floats set to "" through attributes= remain
as NULL. This was especially a problem for scaffolding and postgresql.
(#49)

* Changed the MySQL Adapter to rely on MySQL for its defaults for
socket, host, and port [Andreas Schwarz]

* Changed ActionControllerError to decent from StandardError instead of
Exception. It can now be caught by a generic rescue.

* Changed class inheritable attributes to not use eval [Caio Chassot]

* Changed Errors#add to now use "invalid" as the default message
instead of true, which means full_messages work with those [Marcel
Molina Jr]

* Fixed spelling on Base#add_on_boundry_breaking to
Base#add_on_boundary_breaking (old naming still works) [Marcel Molina
Jr.]

* Fixed that entries in the has_and_belongs_to_many join table didn't
get removed when an associated object was destroyed.

* Fixed unnecessary calls to SET AUTOCOMMIT=0/1 for MySQL adapter
[Andreas Schwarz]

* Fixed PostgreSQL defaults are now handled gracefully [Dave Steinberg]

* Fixed increment/decrement_counter are now atomic updates [Andreas
Schwarz]

* Fixed the problems the Inflector had turning Attachment into
attuchments and Cases into Casis [radsaq/Florian Gross]

* Fixed that cloned records would point attribute references on the
parent object [Andreas Schwarz]

* Fixed SQL for type call on inheritance hierarchies [Caio Chassot]

* Fixed bug with typed inheritance [Florian Weber]

* Fixed a bug where has_many collection_count wouldn't use the
conditions specified for that association



Action Pack 0.9.0: Builder-based templates, functional testing,
performance
========================================================================
===

* Added support for Builder-based templates for files with the .rxml
extension. These new templates are an alternative to ERb that are
especially useful for generating XML content, such as this RSS example
from 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

...which will generate something like:

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Web Site Redesign</title>
<link>http://www.basecamphq.com/clients/travelcenter/1/</link>
<description>Basecamp: Recent items</description>
<language>en-us</language>
<ttl>40</ttl>
<item>
<title>Post: don't you know</title>
<description>&amp;lt;p&amp;gt;deeper and
down&amp;lt;/p&amp;gt;</description>
<pubDate>Fri, 20 Aug 2004 21:13:50 CEST</pubDate>

<guid>http://www.basecamphq.com/clients/travelcenter/1/msg/assets/
96976/comments</guid>

<link>http://www.basecamphq.com/clients/travelcenter/1/msg/assets/
96976/comments</link>
<dc:creator>David H. Heinemeier</dc:creator>
</item>
<item>
<title>Milestone completed: Design Comp 2</title>
<pubDate>Mon, 9 Aug 2004 14:42:06 CEST</pubDate>

<guid>http://www.basecamphq.com/clients/travelcenter/1/milestones/#49</
guid>

<link>http://www.basecamphq.com/clients/travelcenter/1/milestones/#49</
link>
</item>
</channel>
</rss>

The "xml" local variable is automatically available in .rxml templates.
You construct the template by calling a method with the name of the tag
you want. Options for the tag can be specified as a hash parameter to
that method.

Builder-based templates can be mixed and matched with the regular ERb
ones. The only thing that differentiates them is the extension. No new
methods have been added to the public interface to handle them.

Action Pack ships with a version of Builder, but it will use the
RubyGems version if you have one installed.

Read more about Builder on:
http://onestepback.org/index.cgi/Tech/Ruby/StayingSimple.rdoc

[Builder is created by Jim Weirich]

* Added much improved support for functional testing [what-a-day].

# Old style
def test_failing_authenticate
@request.request_uri = "/login/authenticate"
@request.action = "authenticate"
@request.request_parameters["user_name"] = "nop"
@request.request_parameters["password"] = ""

response = LoginController.process_test(@request)

assert_equal "The username and/or password you entered is
invalid.", response.session["flash"]["alert"]
assert_equal "http://37signals.basecamp.com/login/",
response.headers["location"]
end

# New style
def test_failing_authenticate
process :authenticate, "user_name" => "nop", "password" => ""
assert_flash_has 'alert'
assert_redirected_to :action => "index"
end

See a full example on http://codepaste.org/view/paste/334

* Increased performance by up to 100% with a revised 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

* Added caching for compiled ERb templates. On Basecamp, it gave
between 8.5% and 71% increase in performance [Andreas Schwarz].

* Added implicit counter variable to render_collection_of_partials
[Marcel]. From the docs:

<%= render_collection_of_partials "ad", @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+.

* Fixed problems with two sessions being maintained on reset_session
that would particularly screw up ActiveRecordStore.

* Fixed reset_session to start an entirely new session instead of
merely deleting the old. So you can now safely access @session after
calling reset_ression and expect it to work.

* Added @request.get?, @request.post?, @request.put?, @request.delete?
as convenience query methods for @request.method [geech]

* Added @request.method that'll return a symbol representing the HTTP
method, such as :get, :post, :put, :delete [geech]

* Changed @request.remote_ip and @request.host to work properly even
when a proxy is in front of the application [geech]

* Added JavaScript confirm feature to link_to. Documentation:

The html_options have a special feature 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.

* Added link_to_unless_current as a UrlHelper method [Sam Stephenson].
Documentation:

Creates a link tag of the given +name+ using an URL created by the
set of +options+, unless the current
controller, action, and id are 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.

* Fixed that UrlRewriter (the driver for url_for, link_to, etc) would
blow up when the anchor was an integer [alexey]

* Added that layouts defined with no directory defaults to layouts. So
layout "weblog/standard" will use
weblog/standard (as always), but layout "standard" will use
layouts/standard.

* Fixed that partials (or any template starting with an underscore) was
publically viewable [Marten]

* Added HTML escaping to text_area helper.

* Added :eek:verwrite_params to url_for and friends to keep the parameters
as they were passed to the current action and only overwrite a subset.
The regular :params will clear the slate so you need to manually add in
existing parameters if you want to reuse them. [raphinou]

* Fixed scaffolding problem with composite named objects [Moo Jester]

* Added the possibility for shared partials. Example:

<%= render_partial "advertisement/ad", ad %>

This will render the partial "advertisement/_ad.rhtml" regardless of
which controller this is being called from.

[Jacob Fugal]

* Fixed crash when encountering forms that have empty-named fields
[James Prudente]

* Added check_box form helper method now accepts true/false as well as
1/0 [what-a-day]

* Fixed the lacking creation of all directories with install.rb [Dave
Steinberg]

* Fixed that date_select returns valid XHTML selected options [Andreas
Schwarz]

* Fixed referencing an action with the same name as a controller in
url_for [what-a-day]

* Fixed the destructive nature of Base#attributes= on the argument
[Kevin Watt]

* Changed ActionControllerError to decent from StandardError instead of
Exception. It can now be caught by a generic rescue.

* Added SessionRestoreError that is raised when a session being
restored holds objects where there is no class available.

* Added block as option for inline filters. So what used to be written
as:

before_filter Proc { |controller| return false if
controller.params["stop_action"] }

...can now be as:

before_filter { |controller| return false if
controller.params["stop_action"] }

[Jeremy Kemper]

* Made the following methods public (was protected): url_for,
controller_class_name, controller_name, action_name
This makes it easier to write filters without cheating around the
encapsulation with send.

* ActionController::Base#reset_session now sticks even if you access
@session afterwards [Kent Sibilev]

* Improved the exception logging so the log file gets almost as much as
in-browser debugging.

* Changed base class setup from AbstractTemplate/ERbTemplate to
ActionView::Base. This change should be harmless unless you were
accessing Action View directly in which case you now need to reference
the Base class.\

* Added that render_collection_of_partials returns nil if the
collection is empty. This makes showing a “no items” message easier.
For example: <%= render_collection_of_partials("message", @messages) ||
"No messages found." %> [Sam Stephenson]

* Added :month_before_year as an option to date_select to get the month
select before the year. Especially useful for credit card forms.

* Added :add_month_numbers to select_month to get options like "3 -
March".

* Removed Base.has_active_layout? as it couldn't answer the question
without the instance. Use Base#active_layout instead.

* Removed redundant call to update on
ActionController::Base#close_session [Andreas Schwarz]

* Fixed that DRb Store accidently started its own server (instead of
just client) [Andreas]

* Fixed strip_links so it now works across multiple lines [Chad Fowler]

* Fixed the TemplateError exception to show the proper trace on to_s
(useful for unit test debugging)

* Implemented class inheritable attributes without eval [Caio Chassot]

* Made TextHelper#concat accept binding as it would otherwise not work

* The FormOptionsHelper will now call to_s on the keys and values used
to generate options
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top