提交 d53b5f07 编写于 作者: A Aaron Patterson

Merge branch 'master' into normalizecb

* master: (61 commits)
  add tests for reset_calbacks
  Fixing build broken by this change
  Extract variable out of loop
  Updated comment to Rails 4
  Fixes NoMethodError: `alias_method_chain` when requiring just active_support/core_ext
  better error message when app name is not passed in `rails new`
  Code cleanup for ActionDispatch::Flash#call
  Fix typo: require -> requires
  Add CHANGELOG entry for #10576
  Merge pull request #10556 from Empact/deprecate-schema-statements-distinct
  Some editorial changes on the documentation.
  respond_to -> respond to in a message from AM::Lint
  specify that dom_(id|class) are deprecated in controllers, views are fine
  copy edits [ci skip]
  Fix class and method name typos
  Replace multi_json with json
  ruby -> Ruby
  Adding documentation to the automatic inverse_of finder.
  Improve CHANGELOG entry [ci kip]
  Call assume_migrated_upto_version on connection
  ...

Conflicts:
	activesupport/lib/active_support/callbacks.rb
......@@ -60,11 +60,6 @@ platforms :jruby do
gem 'json'
gem 'activerecord-jdbcsqlite3-adapter', '>= 1.2.7'
# This is needed by now to let tests work on JRuby
# TODO: When the JRuby guys merge jruby-openssl in
# jruby this will be removed
gem 'jruby-openssl'
group :db do
gem 'activerecord-jdbcmysql-adapter', '>= 1.2.7'
gem 'activerecord-jdbcpostgresql-adapter', '>= 1.2.7'
......
......@@ -398,7 +398,7 @@ def register_interceptors(*interceptors)
# Register an Observer which will be notified when mail is delivered.
# Either a class or a string can be passed in as the Observer. If a string is passed in
# it will be <tt>constantize</tt>d.
# it will be +constantize+d.
def register_observer(observer)
delivery_observer = (observer.is_a?(String) ? observer.constantize : observer)
Mail.register_observer(delivery_observer)
......@@ -412,12 +412,20 @@ def register_interceptor(interceptor)
Mail.register_interceptor(delivery_interceptor)
end
# Returns the name of current mailer. This method is also being used as a path for a view lookup.
# If this is an anonymous mailer, this method will return +anonymous+ instead.
def mailer_name
@mailer_name ||= anonymous? ? "anonymous" : name.underscore
end
# Allows to set the name of current mailer.
attr_writer :mailer_name
alias :controller_path :mailer_name
# Sets the defaults through app configuration:
#
# config.action_mailer.default { from: "no-reply@example.org" }
#
# Aliased by ::default_options=
def default(value = nil)
self.default_params = default_params.merge(value).freeze if value
default_params
......@@ -429,13 +437,15 @@ def default(value = nil)
# 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 raw email string as a parameter:
# 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 raw email string
# as a parameter:
#
# class MyMailer < ActionMailer::Base
# def receive(mail)
# ...
# # ...
# end
# end
def receive(raw_mail)
......@@ -446,10 +456,12 @@ def receive(raw_mail)
end
end
# Wraps an email delivery inside of Active Support Notifications instrumentation. This
# method is actually called by the <tt>Mail::Message</tt> object itself through a callback
# when you call <tt>:deliver</tt> on the Mail::Message, calling +deliver_mail+ directly
# and passing a Mail::Message will do nothing except tell the logger you sent the email.
# Wraps an email delivery inside of ActiveSupport::Notifications instrumentation.
#
# This method is actually called by the Mail::Message object itself
# through a callback when you call +:deliver+ on the Mail::Message,
# calling +deliver_mail+ directly and passing a Mail::Message will do
# nothing except tell the logger you sent the email.
def deliver_mail(mail) #:nodoc:
ActiveSupport::Notifications.instrument("deliver.action_mailer") do |payload|
set_payload_for_mail(payload, mail)
......@@ -475,7 +487,7 @@ def set_payload_for_mail(payload, mail) #:nodoc:
payload[:mail] = mail.encoded
end
def method_missing(method_name, *args)
def method_missing(method_name, *args) # :nodoc:
if respond_to?(method_name)
new(method_name, *args).message
else
......@@ -512,17 +524,18 @@ def method_missing(*args)
end
end
# Returns the name of the mailer object.
def mailer_name
self.class.mailer_name
end
# Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> object
# which will add them to itself.
# Allows you to pass random and unusual headers to the new Mail::Message
# object which will add them to itself.
#
# headers['X-Special-Domain-Specific-Header'] = "SecretValue"
#
# You can also pass a hash into headers of header field names and values, which
# will then be set on the Mail::Message object:
# You can also pass a hash into headers of header field names and values,
# which will then be set on the Mail::Message object:
#
# headers 'X-Special-Domain-Specific-Header' => "SecretValue",
# 'In-Reply-To' => incoming.message_id
......@@ -578,22 +591,22 @@ def attachments
# Both methods accept a headers hash. This hash allows you to specify the most used headers
# in an email message, these are:
#
# * <tt>:subject</tt> - The subject of the message, if this is omitted, Action Mailer will
# ask the Rails I18n class for a translated <tt>:subject</tt> in the scope of
# * +:subject+ - The subject of the message, if this is omitted, Action Mailer will
# ask the Rails I18n class for a translated +:subject+ in the scope of
# <tt>[mailer_scope, action_name]</tt> or if this is missing, will translate the
# humanized version of the <tt>action_name</tt>
# * <tt>:to</tt> - Who the message is destined for, can be a string of addresses, or an array
# humanized version of the +action_name+
# * +:to+ - Who the message is destined for, can be a string of addresses, or an array
# of addresses.
# * <tt>:from</tt> - Who the message is from
# * <tt>:cc</tt> - Who you would like to Carbon-Copy on this email, can be a string of addresses,
# * +:from+ - Who the message is from
# * +:cc+ - Who you would like to Carbon-Copy on this email, can be a string of addresses,
# or an array of addresses.
# * <tt>:bcc</tt> - Who you would like to Blind-Carbon-Copy on this email, can be a string of
# * +:bcc+ - Who you would like to Blind-Carbon-Copy on this email, can be a string of
# addresses, or an array of addresses.
# * <tt>:reply_to</tt> - Who to set the Reply-To header of the email to.
# * <tt>:date</tt> - The date to say the email was sent on.
# * +:reply_to+ - Who to set the Reply-To header of the email to.
# * +:date+ - The date to say the email was sent on.
#
# You can set default values for any of the above headers (except :date) by using the <tt>default</tt>
# class method:
# You can set default values for any of the above headers (except +:date+)
# by using the ::default class method:
#
# class Notifier < ActionMailer::Base
# default from: 'no-reply@test.lindsaar.net',
......@@ -605,17 +618,19 @@ def attachments
# as part of the headers hash or use the <tt>headers['name'] = value</tt>
# method.
#
# When a <tt>:return_path</tt> is specified as header, that value will be used as the 'envelope from'
# address for the Mail message. Setting this is useful when you want delivery notifications
# sent to a different address than the one in <tt>:from</tt>. Mail will actually use the
# <tt>:return_path</tt> in preference to the <tt>:sender</tt> in preference to the <tt>:from</tt>
# field for the 'envelope from' value.
# When a +:return_path+ is specified as header, that value will be used as
# the 'envelope from' address for the Mail message. Setting this is useful
# when you want delivery notifications sent to a different address than the
# one in +:from+. Mail will actually use the +:return_path+ in preference
# to the +:sender+ in preference to the +:from+ field for the 'envelope
# from' value.
#
# If you do not pass a block to the +mail+ method, it will find all templates in the
# view paths using by default the mailer name and the method name that it is being
# called from, it will then create parts for each of these templates intelligently,
# making educated guesses on correct content type and sequence, and return a fully
# prepared Mail::Message ready to call <tt>:deliver</tt> on to send.
# If you do not pass a block to the +mail+ method, it will find all
# templates in the view paths using by default the mailer name and the
# method name that it is being called from, it will then create parts for
# each of these templates intelligently, making educated guesses on correct
# content type and sequence, and return a fully prepared Mail::Message
# ready to call +:deliver+ on to send.
#
# For example:
#
......@@ -650,8 +665,8 @@ def attachments
# format.html { render text: "<h1>Hello Mikel!</h1>" }
# end
#
# Which will render a <tt>multipart/alternative</tt> email with <tt>text/plain</tt> and
# <tt>text/html</tt> parts.
# Which will render a +multipart/alternative+ email with +text/plain+ and
# +text/html+ parts.
#
# The block syntax also allows you to customize the part headers if desired:
#
......
......@@ -46,8 +46,9 @@ def format_paragraph(text, len = 72, indent = 2)
end
end
indentation = " " * indent
sentences.map { |sentence|
"#{" " * indent}#{sentence.join(' ')}"
"#{indentation}#{sentence.join(' ')}"
}.join "\n"
end
end
......
......@@ -243,15 +243,9 @@ def call(env)
session = Request::Session.find(env) || {}
flash_hash = env[KEY]
if flash_hash
if !flash_hash.empty? || session.key?('flash')
if flash_hash && (flash_hash.present? || session.key?('flash'))
session["flash"] = flash_hash.to_session_value
new_hash = flash_hash.dup
else
new_hash = flash_hash
end
env[KEY] = new_hash
env[KEY] = flash_hash.dup
end
if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
......
......@@ -62,7 +62,7 @@ def teardown
$stderr = StringIO.new # suppress the log
json = "[\"person]\": {\"name\": \"David\"}}"
exception = assert_raise(ActionDispatch::ParamsParser::ParseError) { post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => false} }
assert_equal MultiJson::DecodeError, exception.original_exception.class
assert_equal JSON::ParserError, exception.original_exception.class
assert_equal exception.original_exception.message, exception.message
ensure
$stderr = STDERR
......
......@@ -98,7 +98,7 @@ def test_errors_aref
private
def model
assert @model.respond_to?(:to_model), "The object should respond_to to_model"
assert @model.respond_to?(:to_model), "The object should respond to to_model"
@model.to_model
end
......
* Deprecate `ConnectionAdapters::SchemaStatements#distinct`,
as it is no longer used by internals.
*Ben Woosley#
* Fix pending migrations error when loading schema and `ActiveRecord::Base.table_name_prefix`
is not blank.
Call `assume_migrated_upto_version` on connection to prevent it from first
being picked up in `method_missing`.
In the base class, `Migration`, `method_missing` expects the argument to be a
table name, and calls `proper_table_name` on the arguments before sending to
`connection`. If `table_name_prefix` or `table_name_suffix` is used, the schema
version changes to `prefix_version_suffix`, breaking `rake test:prepare`.
Fixes #10411.
*Kyle Stevens*
* Method `read_attribute_before_type_cast` should accept input as symbol.
*Neeraj Singh*
* Confirm a record has not already been destroyed before decrementing counter cache.
*Ben Tucker*
......
......@@ -175,7 +175,7 @@ by relying on a number of conventions that make it easy for Active Record to inf
complex relations and structures from a minimal amount of explicit direction.
Convention over Configuration:
* No XML-files!
* No XML files!
* Lots of reflection and run-time extension
* Magic is not inherently a bad word
......
......@@ -172,7 +172,7 @@ def association_instance_set(name, association)
@association_cache[name] = association
end
# Associations are a set of macro-like class methods for tying objects together through
# \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
......@@ -365,11 +365,11 @@ def association_instance_set(name, association)
# there is some special behavior you should be aware of, mostly involving the saving of
# associated objects.
#
# You can set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
# You can set the <tt>:autosave</tt> option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
# <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
# to +true+ will _always_ save the members, whereas setting it to +false+ will
# _never_ save the members. More details about :autosave option is available at
# autosave_association.rb .
# _never_ save the members. More details about <tt>:autosave</tt> option is available at
# AutosaveAssociation.
#
# === One-to-one associations
#
......@@ -402,7 +402,7 @@ def association_instance_set(name, association)
#
# == Customizing the query
#
# Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax
# \Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax
# to customize them. For example, to add a condition:
#
# class Blog < ActiveRecord::Base
......@@ -568,6 +568,8 @@ def association_instance_set(name, association)
# @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
# @group.avatars.delete(@group.avatars.last) # so would this
#
# == Setting Inverses
#
# If you are using a +belongs_to+ on the join model, it is a good idea to set the
# <tt>:inverse_of</tt> option on the +belongs_to+, which will mean that the following example
# works correctly (where <tt>tags</tt> is a +has_many+ <tt>:through</tt> association):
......@@ -584,7 +586,26 @@ def association_instance_set(name, association)
# belongs_to :tag, inverse_of: :taggings
# end
#
# == Nested Associations
# If you do not set the +:inverse_of+ record, the association will do its
# best to match itself up with the correct inverse. Automatic +:inverse_of+
# detection only works on +has_many+, +has_one+, and +belongs_to+ associations.
#
# Extra options on the associations, as defined in the
# <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> constant, will
# also prevent the association's inverse from being found automatically.
#
# The automatic guessing of the inverse association uses a heuristic based
# on the name of the class, so it may not work for all associations,
# especially the ones with non-standard names.
#
# You can turn off the automatic detection of inverse associations by setting
# the +:automatic_inverse_of+ option to +false+ like so:
#
# class Taggable < ActiveRecord::Base
# belongs_to :tag, automatic_inverse_of: false
# end
#
# == Nested \Associations
#
# You can actually specify *any* association with the <tt>:through</tt> option, including an
# association which has a <tt>:through</tt> option itself. For example:
......@@ -627,7 +648,7 @@ def association_instance_set(name, association)
# add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
# intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
#
# == Polymorphic Associations
# == 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
......@@ -789,7 +810,7 @@ def association_instance_set(name, association)
# For example if all the addressables are either of class Person or Company then a total
# of 3 queries will be executed. The list of addressable types to load is determined on
# the back of the addresses loaded. This is not supported if Active Record has to fallback
# to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
# to the previous implementation of eager loading and will raise <tt>ActiveRecord::EagerLoadPolymorphicError</tt>.
# The reason is that the parent model's type is a column value so its corresponding table
# name cannot be put in the +FROM+/+JOIN+ clauses of that query.
#
......@@ -1024,7 +1045,7 @@ module ClassMethods
# An empty array is returned if none are found.
# [collection<<(object, ...)]
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
# Note that this operation instantly fires update sql without waiting for the save or update call on the
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
# parent object, unless the parent object is a new record.
# [collection.delete(object, ...)]
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
......@@ -1060,10 +1081,10 @@ module ClassMethods
# [collection.size]
# Returns the number of associated objects.
# [collection.find(...)]
# Finds an associated object according to the same rules as ActiveRecord::Base.find.
# Finds an associated object according to the same rules as <tt>ActiveRecord::Base.find</tt>.
# [collection.exists?(...)]
# Checks whether an associated object with the given conditions exists.
# Uses the same rules as ActiveRecord::Base.exists?.
# Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>.
# [collection.build(attributes = {}, ...)]
# Returns one or more new objects of the collection type that have been instantiated
# with +attributes+ and linked to this object through a foreign key, but have not yet
......@@ -1082,7 +1103,7 @@ module ClassMethods
#
# === Example
#
# Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
# A <tt>Firm</tt> class declares <tt>has_many :clients</tt>, which will add:
# * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
# * <tt>Firm#clients<<</tt>
# * <tt>Firm#clients.delete</tt>
......@@ -1116,8 +1137,8 @@ module ClassMethods
# Controls what happens to the associated objects when
# their owner is destroyed. Note that these are implemented as
# callbacks, and Rails executes callbacks in order. Therefore, other
# similar callbacks may affect the :dependent behavior, and the
# :dependent behavior may affect other callbacks.
# similar callbacks may affect the <tt>:dependent</tt> behavior, and the
# <tt>:dependent</tt> behavior may affect other callbacks.
#
# * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
# * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
......@@ -1163,8 +1184,8 @@ module ClassMethods
# If true, always save the associated objects or destroy them if marked for destruction,
# when saving the parent object. If false, never save or destroy the associated objects.
# By default, only save associated objects that are new records. This option is implemented as a
# before_save callback. Because callbacks are run in the order they are defined, associated objects
# may need to be explicitly saved in any user-defined before_save callbacks.
# +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
# may need to be explicitly saved in any user-defined +before_save+ callbacks.
#
# Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
# [:inverse_of]
......@@ -1189,7 +1210,7 @@ def has_many(name, scope = nil, options = {}, &extension)
# Specifies a one-to-one association with another class. This method should only be used
# if the other class contains the foreign key. If the current class contains the foreign key,
# then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview
# on when to use has_one and when to use belongs_to.
# on when to use +has_one+ and when to use +belongs_to+.
#
# The following methods for retrieval and query of a single associated object will be added:
#
......@@ -1357,7 +1378,7 @@ def has_one(name, scope = nil, options = {})
# class is created and decremented when it's destroyed. This requires that a column
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
# is used on the associate class (such as a Post class) - that is the migration for
# <tt>#{table_name}_count</tt> is created on the associate class (such that Post.comments_count will
# <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will
# return the count cached, see note below). You can also specify a custom counter
# cache column by providing a column name instead of a +true+/+false+ value to this
# option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
......@@ -1439,7 +1460,7 @@ def belongs_to(name, scope = nil, options = {})
# [collection<<(object, ...)]
# Adds one or more objects to the collection by creating associations in the join table
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
# Note that this operation instantly fires update sql without waiting for the save or update call on the
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
# parent object, unless the parent object is a new record.
# [collection.delete(object, ...)]
# Removes one or more objects from the collection by removing their associations from the join table.
......@@ -1462,10 +1483,10 @@ def belongs_to(name, scope = nil, options = {})
# [collection.find(id)]
# Finds an associated object responding to the +id+ and that
# meets the condition that it has to be associated with this object.
# Uses the same rules as ActiveRecord::Base.find.
# Uses the same rules as <tt>ActiveRecord::Base.find</tt>.
# [collection.exists?(...)]
# Checks whether an associated object with the given conditions exists.
# Uses the same rules as ActiveRecord::Base.exists?.
# Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>.
# [collection.build(attributes = {})]
# Returns a new object of the collection type that has been instantiated
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
......
......@@ -41,8 +41,9 @@ module BeforeTypeCast
# task.read_attribute_before_type_cast('id') # => '1'
# task.read_attribute('completed_on') # => Sun, 21 Oct 2012
# task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
# task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
def read_attribute_before_type_cast(attr_name)
@attributes[attr_name]
@attributes[attr_name.to_s]
end
# Returns a hash of attributes before typecasting and deserialization.
......
......@@ -65,8 +65,7 @@ def columns; @columns_hash.values; 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, type = :primary_key, options = {})
options[:primary_key] = true
column(name, type, options)
column(name, type, options.merge(:primary_key => true))
end
# Returns a ColumnDefinition for the column with name +name+.
......
......@@ -710,6 +710,7 @@ def add_column_options!(sql, options) #:nodoc:
# distinct("posts.id", ["posts.created_at desc"])
#
def distinct(columns, order_by)
ActiveSupport::Deprecation.warn("#distinct is deprecated and shall be removed from future releases.")
"DISTINCT #{columns_for_distinct(columns, order_by)}"
end
......@@ -718,7 +719,7 @@ def distinct(columns, order_by)
# require the order columns appear in the SELECT.
#
# columns_for_distinct("posts.id", ["posts.created_at desc"])
def columns_for_distinct(columns, orders)
def columns_for_distinct(columns, orders) # :nodoc:
columns
end
......
......@@ -668,6 +668,7 @@ def copy(destination, sources, options = {})
copied
end
# Determines the version number of the next migration.
def next_migration_number(number)
if ActiveRecord::Base.timestamped_migrations
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
......
......@@ -8,7 +8,7 @@ module Reflection # :nodoc:
self.reflections = {}
end
# Reflection enables to interrogate Active Record classes and objects
# \Reflection enables to interrogate Active Record classes and objects
# about their associations and aggregations. This information can,
# for example, be used in a form builder that takes an Active Record object
# and creates input fields for all of the attributes depending on their type
......@@ -100,7 +100,7 @@ class MacroReflection
# Returns the hash of options used for the macro.
#
# <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>{ class_name: "Money" }</tt>
# <tt>has_many :clients</tt> returns +{}+
# <tt>has_many :clients</tt> returns <tt>{}</tt>
attr_reader :options
attr_reader :active_record
......@@ -449,8 +449,8 @@ def valid_inverse_reflection?(reflection)
# Checks to see if the reflection doesn't have any options that prevent
# us from being able to guess the inverse automatically. First, the
# +automatic_inverse_of+ option cannot be set to false. Second, we must
# have :has_many, :has_one, :belongs_to associations. Third, we must
# not have options such as :class_name or :polymorphic which prevent us
# have +has_many+, +has_one+, +belongs_to+ associations. Third, we must
# not have options such as +:polymorphic+ or +:foreign_key+ which prevent us
# from correctly guessing the inverse association.
#
# Anything with a scope can additionally ruin our attempt at finding an
......@@ -493,7 +493,7 @@ class ThroughReflection < AssociationReflection #:nodoc:
delegate :foreign_key, :foreign_type, :association_foreign_key,
:active_record_primary_key, :type, :to => :source_reflection
# Gets the source of the through reflection. It checks both a singularized
# Returns the source of the through reflection. It checks both a singularized
# and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>.
#
# class Post < ActiveRecord::Base
......@@ -507,8 +507,7 @@ class ThroughReflection < AssociationReflection #:nodoc:
# end
#
# tags_reflection = Post.reflect_on_association(:tags)
#
# taggings_reflection = tags_reflection.source_reflection
# tags_reflection.source_reflection
# # => <ActiveRecord::Reflection::AssociationReflection: @macro=:belongs_to, @name=:tag, @active_record=Tagging, @plural_name="tags">
#
def source_reflection
......@@ -524,7 +523,8 @@ def source_reflection
# end
#
# tags_reflection = Post.reflect_on_association(:tags)
# taggings_reflection = tags_reflection.through_reflection
# tags_reflection.through_reflection
# # => <ActiveRecord::Reflection::AssociationReflection: @macro=:has_many, @name=:taggings, @active_record=Post, @plural_name="taggings">
#
def through_reflection
@through_reflection ||= active_record.reflect_on_association(options[:through])
......
......@@ -340,6 +340,9 @@ def reorder!(*args) # :nodoc:
# User.where(name: "John", active: true).unscope(where: :name)
# == User.where(active: true)
#
# This method is applied before the default_scope is applied. So the conditions
# specified in default_scope will not be removed.
#
# Note that this method is more generalized than ActiveRecord::SpawnMethods#except
# because #except will only affect a particular relation's values. It won't wipe
# the order, grouping, etc. when that relation is merged. For example:
......
......@@ -43,7 +43,7 @@ def define(info, &block) # :nodoc:
unless info[:version].blank?
initialize_schema_migrations_table
assume_migrated_upto_version(info[:version], migrations_paths)
connection.assume_migrated_upto_version(info[:version], migrations_paths)
end
end
......
......@@ -14,6 +14,10 @@ def create_migration_file
protected
attr_reader :migration_action, :join_tables
# sets the default migration template that is being used for the generation of the migration
# depending on the arguments which would be sent out in the command line, the migration template
# and the table name instance variables are setup.
def set_local_assigns!
@migration_template = "migration.rb"
case file_name
......
......@@ -226,9 +226,11 @@ def test_partial_index
end
def test_distinct_zero_orders
assert_deprecated do
assert_equal "DISTINCT posts.id",
@connection.distinct("posts.id", [])
end
end
def test_columns_for_distinct_zero_orders
assert_equal "posts.id",
......@@ -236,9 +238,11 @@ def test_columns_for_distinct_zero_orders
end
def test_distinct_one_order
assert_deprecated do
assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
@connection.distinct("posts.id", ["posts.created_at desc"])
end
end
def test_columns_for_distinct_one_order
assert_equal "posts.id, posts.created_at AS alias_0",
......@@ -246,9 +250,11 @@ def test_columns_for_distinct_one_order
end
def test_distinct_few_orders
assert_deprecated do
assert_equal "DISTINCT posts.id, posts.created_at AS alias_0, posts.position AS alias_1",
@connection.distinct("posts.id", ["posts.created_at desc", "posts.position asc"])
end
end
def test_columns_for_distinct_few_orders
assert_equal "posts.id, posts.created_at AS alias_0, posts.position AS alias_1",
......@@ -256,9 +262,11 @@ def test_columns_for_distinct_few_orders
end
def test_distinct_blank_not_nil_orders
assert_deprecated do
assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
@connection.distinct("posts.id", ["posts.created_at desc", "", " "])
end
end
def test_columns_for_distinct_blank_not_nil_orders
assert_equal "posts.id, posts.created_at AS alias_0",
......@@ -270,9 +278,11 @@ def test_distinct_with_arel_order
def order.to_sql
"posts.created_at desc"
end
assert_deprecated do
assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
@connection.distinct("posts.id", [order])
end
end
def test_columns_for_distinct_with_arel_order
order = Object.new
......@@ -284,9 +294,11 @@ def order.to_sql
end
def test_distinct_with_nulls
assert_deprecated do
assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls first"])
assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls last"])
end
end
def test_columns_for_distinct_with_nulls
assert_equal "posts.title, posts.updater_id AS alias_0", @connection.columns_for_distinct("posts.title", ["posts.updater_id desc nulls first"])
......
......@@ -12,6 +12,8 @@ def setup
def teardown
@connection.drop_table :fruits rescue nil
@connection.drop_table :nep_fruits rescue nil
@connection.drop_table :nep_schema_migrations rescue nil
ActiveRecord::SchemaMigration.delete_all rescue nil
end
......@@ -30,6 +32,24 @@ def test_schema_define
assert_equal 7, ActiveRecord::Migrator::current_version
end
def test_schema_define_w_table_name_prefix
table_name = ActiveRecord::SchemaMigration.table_name
ActiveRecord::Base.table_name_prefix = "nep_"
ActiveRecord::SchemaMigration.table_name = "nep_#{table_name}"
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_equal 7, ActiveRecord::Migrator::current_version
ensure
ActiveRecord::Base.table_name_prefix = ""
ActiveRecord::SchemaMigration.table_name = table_name
end
def test_schema_raises_an_error_for_invalid_column_type
assert_raise NoMethodError do
ActiveRecord::Schema.define(:version => 8) do
......
......@@ -130,6 +130,7 @@ def test_id_before_type_cast_with_custom_primary_key
assert_equal '10', keyboard.id_before_type_cast
assert_equal nil, keyboard.read_attribute_before_type_cast('id')
assert_equal '10', keyboard.read_attribute_before_type_cast('key_number')
assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
end
# Syck calls respond_to? before actually calling initialize
......
......@@ -235,7 +235,7 @@ def test_change_column_quotes_column_names
end
end
def test_keeping_default_and_notnull_constaint_on_change
def test_keeping_default_and_notnull_constraints_on_change
connection.create_table :testings do |t|
t.column :title, :string
end
......
......@@ -18,7 +18,7 @@
require 'models/toy'
require 'rexml/document'
class PersistencesTest < ActiveRecord::TestCase
class PersistenceTest < ActiveRecord::TestCase
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts, :minivans, :pets, :toys
# Oracle UPDATE does not support ORDER BY
......
......@@ -205,7 +205,7 @@ def test_set_primary_key_with_no_connection
class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def test_primaery_key_method_with_ansi_quotes
def test_primary_key_method_with_ansi_quotes
con = ActiveRecord::Base.connection
con.execute("SET SESSION sql_mode='ANSI_QUOTES'")
assert_equal "id", con.primary_key("topics")
......
* Replace `multi_json` with `json`.
Since Rails requires Ruby 1.9 and since Ruby 1.9 includes `json` in the standard library,
`multi_json` is no longer necessary.
*Erik Michaels-Ober*
* Added escaping of U+2028 and U+2029 inside the json encoder.
These characters are legal in JSON but break the Javascript interpreter.
After escaping them, the JSON is still legal and can be parsed by Javascript.
*Mario Caropreso + Viktor Kelemen + zackham*
* Fix skipping object callbacks using metadata fetched via callback chain
inspection methods (`_*_callbacks`)
......
......@@ -21,7 +21,7 @@
s.rdoc_options.concat ['--encoding', 'UTF-8']
s.add_dependency('i18n', '~> 0.6', '>= 0.6.4')
s.add_dependency 'multi_json', '~> 1.3'
s.add_dependency 'json', '~> 1.7'
s.add_dependency 'tzinfo', '~> 0.3.37'
s.add_dependency 'minitest', '~> 4.2'
s.add_dependency 'thread_safe','~> 0.1'
......
require 'active_support/core_ext/module/aliasing'
module Marshal
class << self
def load_with_autoloading(source)
......
require 'active_support/core_ext/module/aliasing'
class Range
# Extends the default Range#include? to support range comparisons.
# (1..5).include?(1..5) # => true
......
......@@ -15,6 +15,7 @@ class String
# "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 05:12:00 UTC
# "12/13/2012".to_time # => ArgumentError: argument out of range
def to_time(form = :local)
parts = Date._parse(self, false)
return if parts.empty?
......
......@@ -185,7 +185,7 @@ def tableize
#
# Singular names are not handled correctly.
#
# 'business'.classify # => "Busines"
# 'business'.classify # => "Business"
def classify
ActiveSupport::Inflector.classify(self)
end
......
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/module/delegation'
require 'multi_json'
require 'json'
module ActiveSupport
# Look for and parse json strings that look like ISO 8601 times.
......@@ -13,8 +13,8 @@ class << self
#
# ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
# => {"team" => "rails", "players" => "36"}
def decode(json, options ={})
data = MultiJson.load(json, options)
def decode(json, proc = nil, options = {})
data = ::JSON.load(json, proc, options)
if ActiveSupport.parse_json_times
convert_dates_from(data)
else
......@@ -22,23 +22,6 @@ def decode(json, options ={})
end
end
def engine
MultiJson.adapter
end
alias :backend :engine
def engine=(name)
MultiJson.use(name)
end
alias :backend= :engine=
def with_backend(name)
old_backend, self.backend = backend, name
yield
ensure
self.backend = old_backend
end
# Returns the class of the error that will be raised when there is an
# error in decoding JSON. Using this method means you won't directly
# depend on the ActiveSupport's JSON implementation, in case it changes
......@@ -50,7 +33,7 @@ def with_backend(name)
# Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
# end
def parse_error
MultiJson::DecodeError
::JSON::ParserError
end
private
......
#encoding: us-ascii
require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/module/delegation'
require 'active_support/json/variable'
......@@ -98,13 +100,18 @@ def check_for_circular_references(value)
"\010" => '\b',
"\f" => '\f',
"\n" => '\n',
"\xe2\x80\xa8" => '\u2028',
"\xe2\x80\xa9" => '\u2029',
"\r" => '\r',
"\t" => '\t',
'"' => '\"',
'\\' => '\\\\',
'>' => '\u003E',
'<' => '\u003C',
'&' => '\u0026' }
'&' => '\u0026',
"#{0xe2.chr}#{0x80.chr}#{0xa8.chr}" => '\u2028',
"#{0xe2.chr}#{0x80.chr}#{0xa9.chr}" => '\u2029',
}
class << self
# If true, use ISO 8601 format for dates and times. Otherwise, fall back
......@@ -121,9 +128,9 @@ class << self
def escape_html_entities_in_json=(value)
self.escape_regex = \
if @escape_html_entities_in_json = value
/[\x00-\x1F"\\><&]/
/\xe2\x80\xa8|\xe2\x80\xa9|[\x00-\x1F"\\><&]/
else
/[\x00-\x1F"\\]/
/\xe2\x80\xa8|\xe2\x80\xa9|[\x00-\x1F"\\]/
end
end
......
......@@ -40,6 +40,14 @@ def respond_to_missing?(name, include_private)
end
end
# +InheritableOptions+ provides a constructor to build an +OrderedOptions+
# hash inherited from the another hash.
#
# Use this if you already have some hash and you want to create a new one based on it.
#
# h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
# h.girl # => 'Mary'
# h.boy # => 'John'
class InheritableOptions < OrderedOptions
def initialize(parent = nil)
if parent.kind_of?(OrderedOptions)
......
......@@ -873,6 +873,46 @@ def test_proc_arity2
end
end
class ResetCallbackTest < ActiveSupport::TestCase
def build_class(memo)
klass = Class.new {
include ActiveSupport::Callbacks
define_callbacks :foo
set_callback :foo, :before, :hello
def run; run_callbacks :foo; end
}
klass.class_eval {
define_method(:hello) { memo << :hi }
}
klass
end
def test_reset_callbacks
events = []
klass = build_class events
klass.new.run
assert_equal 1, events.length
klass.reset_callbacks :foo
klass.new.run
assert_equal 1, events.length
end
def test_reset_impacts_subclasses
events = []
klass = build_class events
subclass = Class.new(klass) { set_callback :foo, :before, :world }
subclass.class_eval { define_method(:world) { events << :world } }
subclass.new.run
assert_equal 2, events.length
klass.reset_callbacks :foo
subclass.new.run
assert_equal 3, events.length
end
end
class CallbackTypeTest < ActiveSupport::TestCase
def build_class(callback, n = 10)
Class.new {
......
......@@ -55,34 +55,24 @@ class TestJSONDecoding < ActiveSupport::TestCase
%q({"a":"Line1\u000aLine2"}) => {"a"=>"Line1\nLine2"}
}
backends = [:ok_json]
backends << :json_gem if defined?(::JSON)
backends << :yajl if defined?(::Yajl)
backends.each do |backend|
TESTS.each do |json, expected|
test "json decodes #{json} with the #{backend} backend" do
test "json decodes #{json}" do
prev = ActiveSupport.parse_json_times
ActiveSupport.parse_json_times = true
silence_warnings do
ActiveSupport::JSON.with_backend backend do
assert_equal expected, ActiveSupport::JSON.decode(json)
end
end
ActiveSupport.parse_json_times = prev
end
end
test "json decodes time json with time parsing disabled with the #{backend} backend" do
test "json decodes time json with time parsing disabled" do
prev = ActiveSupport.parse_json_times
ActiveSupport.parse_json_times = false
expected = {"a" => "2007-01-01 01:12:34 Z"}
ActiveSupport::JSON.with_backend backend do
assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
end
ActiveSupport.parse_json_times = prev
end
end
def test_failed_json_decoding
assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) }
......
......@@ -45,8 +45,8 @@ def as_json(options={})
StringTests = [[ 'this is the <string>', %("this is the \\u003Cstring\\u003E")],
[ 'a "string" with quotes & an ampersand', %("a \\"string\\" with quotes \\u0026 an ampersand") ],
[ 'http://test.host/posts/1', %("http://test.host/posts/1")],
[ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
%("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F") ]]
[ "Control characters: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\342\200\250\342\200\251",
%("Control characters: \\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\\u2028\\u2029") ]]
ArrayTests = [[ ['a', 'b', 'c'], %([\"a\",\"b\",\"c\"]) ],
[ [1, 'a', :b, nil, false], %([1,\"a\",\"b\",null,false]) ]]
......
Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook
icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency
from the Jimmac icons to get round MS IE and FOP PNG incompatibilies.
from the Jimmac icons to get round MS IE and FOP PNG incompatibilities.
Stuart Rackham
......@@ -342,7 +342,7 @@ Helpers that do something else, like `cache` or `content_for`, are not affected
* Helpers now output HTML 5 by default.
* Form label helper now pulls values from I18n with a single value, so `f.label :name` will pull the `:name` translation.
* I18n select label on should now be :en.helpers.select instead of :en.support.select.
* You no longer need to place a minus sign at the end of a ruby interpolation inside an ERb template to remove the trailing carriage return in the HTML output.
* You no longer need to place a minus sign at the end of a Ruby interpolation inside an ERB template to remove the trailing carriage return in the HTML output.
* Added `grouped_collection_select` helper to Action View.
* `content_for?` has been added allowing you to check for the existence of content in a view before rendering.
* passing `:value => nil` to form helpers will set the field's `value` attribute to nil as opposed to using the default value
......@@ -611,4 +611,3 @@ Credits
See the [full list of contributors to Rails](http://contributors.rubyonrails.org/) for the many people who spent many hours making Rails 3. Kudos to all of them.
Rails 3.0 Release Notes were compiled by [Mikel Lindsaar](http://lindsaar.net.)
......@@ -85,7 +85,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railt
* New test locations `test/models`, `test/helpers`, `test/controllers`, and `test/mailers`. Corresponding rake tasks added as well. ([Pull Request](https://github.com/rails/rails/pull/7878))
* Your app's executables now live in the `bin/` dir. Run `rake rails:update:bin` to get `bin/bundle`, `bin/rails`, and `bin/rake`.
* Your app's executables now live in the `bin/` directory. Run `rake rails:update:bin` to get `bin/bundle`, `bin/rails`, and `bin/rake`.
* Threadsafe on by default
......
......@@ -568,10 +568,10 @@ end
Note that while for session values you set the key to `nil`, to delete a cookie value you should use `cookies.delete(:key)`.
Rendering xml and json data
Rendering XML and JSON data
---------------------------
ActionController makes it extremely easy to render `xml` or `json` data. If you've generated a controller using scaffolding, it would look something like this:
ActionController makes it extremely easy to render `XML` or `JSON` data. If you've generated a controller using scaffolding, it would look something like this:
```ruby
class UsersController < ApplicationController
......
......@@ -14,7 +14,7 @@ Active Model is a library containing various modules used in developing framewor
### AttributeMethods
The AttributeMethods module can add custom prefixes and suffixes on methods of a class. It is used by defining the prefixes and suffixes, which methods on the object will use them.
The AttributeMethods module can add custom prefixes and suffixes on methods of a class. It is used by defining the prefixes and suffixes and which methods on the object will use them.
```ruby
class Person
......@@ -45,7 +45,7 @@ person.age_highest? # false
### Callbacks
Callbacks gives Active Record style callbacks. This provides the ability to define the callbacks and those will run at appropriate time. After defining a callbacks you can wrap with before, after and around custom methods.
Callbacks gives Active Record style callbacks. This provides an ability to define callbacks which run at appropriate times. After defining callbacks, you can wrap them with before, after and around custom methods.
```ruby
class Person
......@@ -57,19 +57,19 @@ class Person
def update
run_callbacks(:update) do
# This will call when we are trying to call update on object.
# This method is called when update is called on an object.
end
end
def reset_me
# This method will call when you are calling update on object as a before_update callback as defined.
# This method is called when update is called on an object as a before_update callback is defined.
end
end
```
### Conversion
If a class defines `persisted?` and `id` methods then you can include `Conversion` module in that class and you can able to call Rails conversion methods to objects of that class.
If a class defines `persisted?` and `id` methods, then you can include the `Conversion` module in that class and call the Rails conversion methods on objects of that class.
```ruby
class Person
......
......@@ -732,7 +732,7 @@ The `reorder` method overrides the default scope order. For example:
class Post < ActiveRecord::Base
..
..
has_many :comments, order: 'posted_at DESC'
has_many :comments, -> { order('posted_at DESC') }
end
Post.find(10).comments.reorder('name')
......
......@@ -166,7 +166,7 @@ NOTE: Defined in `active_support/core_ext/object/duplicable.rb`.
### `deep_dup`
The `deep_dup` method returns deep copy of a given object. Normally, when you `dup` an object that contains other objects, ruby does not `dup` them, so it creates a shallow copy of the object. If you have an array with a string, for example, it will look like this:
The `deep_dup` method returns deep copy of a given object. Normally, when you `dup` an object that contains other objects, Ruby does not `dup` them, so it creates a shallow copy of the object. If you have an array with a string, for example, it will look like this:
```ruby
array = ['string']
......
......@@ -430,7 +430,7 @@ in scope in development mode regardless of the value of this flag. Changing this
engines. Engines can define assets for precompilation as well. Since the complete environment is not loaded,
engines (or other gems) will not be loaded, which can cause missing assets.
Capistrano (v2.8.0 and above) includes a recipe to handle this in deployment. Add the following line to `Capfile`:
Capistrano (v2.15.1 and above) includes a recipe to handle this in deployment. Add the following line to `Capfile`:
```ruby
load 'deploy/assets'
......
......@@ -693,6 +693,17 @@ There are a few limitations to `inverse_of` support:
* They do not work with `:as` associations.
* For `belongs_to` associations, `has_many` inverse associations are ignored.
Every association will attempt to automatically find the inverse association
and set the `:inverse_of` option heuristically (based on the association name).
Most associations with standard names will be supported. However, associations
that contain the following options will not have their inverses set
automatically:
* :conditions
* :through
* :polymorphic
* :foreign_key
Detailed Association Reference
------------------------------
......
......@@ -40,7 +40,7 @@ Oscar Del Ben is a software engineer at <a href="http://www.wildfireapp.com/">Wi
<% end %>
<%= author('Tore Darell', 'toretore') do %>
Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails and unobtrusive JavaScript. His home on the internet is his blog <a href="http://tore.darell.no">Sneaky Abstractions</a>.
Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails and unobtrusive JavaScript. His home on the Internet is his blog <a href="http://tore.darell.no">Sneaky Abstractions</a>.
<% end %>
<%= author('Jeff Dean', 'zilkey') do %>
......
......@@ -5,6 +5,10 @@ This guide covers how to setup an environment for Ruby on Rails core development
After reading this guide, you will know:
* How to set up your machine for Rails development
* How to run specific groups of unit tests from the Rails test suite
* How the ActiveRecord portion of the Rails test suite operates
--------------------------------------------------------------------------------
The Easy Way
......@@ -53,7 +57,7 @@ If you are on Fedora or CentOS, you can run
$ sudo yum install libxml2 libxml2-devel libxslt libxslt-devel
```
If you have any problems with these libraries, you should install them manually compiling the source code. Just follow the instructions at the [Red Hat/CentOS section of the Nokogiri tutorials](http://nokogiri.org/tutorials/installing_nokogiri.html#red_hat__centos) .
If you have any problems with these libraries, you can install them manually by compiling the source code. Just follow the instructions at the [Red Hat/CentOS section of the Nokogiri tutorials](http://nokogiri.org/tutorials/installing_nokogiri.html#red_hat__centos) .
Also, SQLite3 and its development files for the `sqlite3-ruby` gem — in Ubuntu you're done with just
......@@ -93,7 +97,7 @@ $ cd actionpack
$ bundle exec rake test
```
If you want to run the tests located in a specific directory use the `TEST_DIR` environment variable. For example, this will run the tests of the `railties/test/generators` directory only:
If you want to run the tests located in a specific directory use the `TEST_DIR` environment variable. For example, this will run the tests in the `railties/test/generators` directory only:
```bash
$ cd railties
......@@ -133,14 +137,14 @@ $ sudo yum install mysql-server mysql-devel
$ sudo yum install postgresql-server postgresql-devel
```
After that run:
After that, run:
```bash
$ rm .bundle/config
$ bundle install
```
We need first to delete `.bundle/config` because Bundler remembers in that file that we didn't want to install the "db" group (alternatively you can edit the file).
First, we need to delete `.bundle/config` because Bundler remembers in that file that we didn't want to install the "db" group (alternatively you can edit the file).
In order to be able to run the test suite against MySQL you need to create a user named `rails` with privileges on the test databases:
......
......@@ -29,7 +29,7 @@ prerequisites installed:
Rails is a web application framework running on the Ruby programming language.
If you have no prior experience with Ruby, you will find a very steep learning
curve diving straight into Rails. There are some good free resources on the
internet for learning Ruby, including:
Internet for learning Ruby, including:
* [Mr. Neighborly's Humble Little Ruby Book](http://www.humblelittlerubybook.com)
* [Programming Ruby](http://www.ruby-doc.org/docs/ProgrammingRuby/)
......@@ -853,8 +853,7 @@ it look as follows:
```html+erb
<h1>Editing post</h1>
<%= form_for :post, url: post_path(@post.id) },
method: :patch do |f| %>
<%= form_for :post, url: post_path(@post.id), method: :patch do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
......@@ -934,7 +933,7 @@ appear next to the "Show" link:
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', post_path %></td>
<td><%= link_to 'Show', post_path(post) %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
......@@ -1076,7 +1075,7 @@ together.
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', post_path %></td>
<td><%= link_to 'Show', post_path(post) %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post_path(post),
method: :delete, data: { confirm: 'Are you sure?' } %></td>
......@@ -1149,19 +1148,17 @@ class CreateComments < ActiveRecord::Migration
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :post
t.references :post, index: true
t.timestamps
end
add_index :comments, :post_id
end
end
```
The `t.references` line sets up a foreign key column for the association between
the two models. And the `add_index` line sets up an index for this association
column. Go ahead and run the migration:
the two models. An index for this association is also created on this column.
Go ahead and run the migration:
```bash
$ rake db:migrate
......@@ -1173,10 +1170,8 @@ run against the current database, so in this case you will just see:
```bash
== CreateComments: migrating =================================================
-- create_table(:comments)
-> 0.0008s
-- add_index(:comments, :post_id)
-> 0.0003s
== CreateComments: migrated (0.0012s) ========================================
-> 0.0115s
== CreateComments: migrated (0.0119s) ========================================
```
### Associating Models
......
......@@ -114,7 +114,7 @@ If we used `s` rather than `server`, Rails will use the `aliases` defined in the
```ruby
when 'server'
# Change to the application's path if there is no config.ru file in current dir.
# Change to the application's path if there is no config.ru file in current directory.
# This allows us to run `rails server` from other directories, but still get
# the main config.ru and properly set the tmp directory.
Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
......
......@@ -852,7 +852,7 @@ end
# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, presence: true
validates :flag, :inclusion => { :in => [true, false] }
end
```
......@@ -877,7 +877,8 @@ end
# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, :fuzz, presence: true
validates :flag, :inclusion => { :in => [true, false] }
validates :fuzz, presence: true
end
```
......
......@@ -857,7 +857,7 @@ resources :user_permissions, controller: 'admin/user_permissions'
This will route to the `Admin::UserPermissions` controller.
NOTE: Only the directory notation is supported. Specifying the
controller with ruby constant notation (eg. `:controller =>
controller with Ruby constant notation (eg. `:controller =>
'Admin::UserPermissions'`) can lead to routing problems and results in
a warning.
......
......@@ -58,7 +58,7 @@ WARNING: _Stealing a user's session id lets an attacker use the web application
Many web applications have an authentication system: a user provides a user name and password, the web application checks them and stores the corresponding user id in the session hash. From now on, the session is valid. On every request the application will load the user, identified by the user id in the session, without the need for new authentication. The session id in the cookie identifies the session.
Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
Hence, the cookie serves as temporary authentication for the web application. Anyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
......@@ -268,7 +268,7 @@ def legacy
end
```
This will redirect the user to the main action if he tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can exploited by an attacker if he includes a host key in the URL:
This will redirect the user to the main action if he tried to access a legacy action. The intention was to preserve the URL parameters to the legacy action and pass them to the main action. However, it can be exploited by an attacker if he includes a host key in the URL:
```
http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com
......@@ -942,7 +942,7 @@ Or you can remove them.
config.action_dispatch.default_headers.clear
```
Here is the list of common headers:
Here is a list of common headers:
* X-Frame-Options
_'SAMEORIGIN' in Rails by default_ - allow framing on same domain. Set it to 'DENY' to deny framing at all or 'ALLOWALL' if you want to allow framing for all website.
......
......@@ -118,7 +118,7 @@ Please read [Pull Request #9978](https://github.com/rails/rails/pull/9978) for d
* Rails 4.0 changes the default memcached client from `memcache-client` to `dalli`. To upgrade, simply add `gem 'dalli'` to your `Gemfile`.
* Rails 4.0 deprecates the `dom_id` and `dom_class` methods. You will need to include the `ActionView::RecordIdentifier` module in controllers requiring this feature.
* Rails 4.0 deprecates the `dom_id` and `dom_class` methods in controllers (they are fine in views). You will need to include the `ActionView::RecordIdentifier` module in controllers requiring this feature.
* Rails 4.0 changed how `assert_generates`, `assert_recognizes`, and `assert_routing` work. Now all these assertions raise `Assertion` instead of `ActionController::RoutingError`.
......
......@@ -151,7 +151,15 @@ class AppGenerator < AppBase # :nodoc:
desc: "Show Rails version number and quit"
def initialize(*args)
raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank?
if args[0].blank?
if args[1].blank?
# rails new
raise Error, "Application name should be provided in arguments. For details run: rails --help"
else
# rails new --skip-bundle my_new_application
raise Error, "Options should be given after the application name. For details run: rails --help"
end
end
super
......
......@@ -4,8 +4,6 @@ source 'https://rubygems.org'
<%= database_gemfile_entry -%>
<%= "gem 'jruby-openssl'\n" if defined?(JRUBY_VERSION) -%>
<%= assets_gemfile_entry %>
<%= javascript_gemfile_entry -%>
......
......@@ -46,18 +46,18 @@ Available field types:
`rails generate model photo title:string album:references`
It will generate an album_id column. You should generate this kind of fields when
you will use a `belongs_to` association for instance. `references` also support
the polymorphism, you could enable the polymorphism like this:
It will generate an `album_id` column. You should generate these kinds of fields when
you will use a `belongs_to` association, for instance. `references` also supports
polymorphism, you can enable polymorphism like this:
`rails generate model product supplier:references{polymorphic}`
For integer, string, text and binary fields an integer in curly braces will
For integer, string, text and binary fields, an integer in curly braces will
be set as the limit:
`rails generate model user pseudo:string{30}`
For decimal two integers separated by a comma in curly braces will be used
For decimal, two integers separated by a comma in curly braces will be used
for precision and scale:
`rails generate model product price:decimal{10,2}`
......
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/<%= name -%>/engine', __FILE__)
......
......@@ -44,11 +44,6 @@ else
end
namespace :doc do
def gem_path(gem_name)
path = $LOAD_PATH.grep(/#{gem_name}[\w.-]*\/lib$/).first
yield File.dirname(path) if path
end
RDocTaskWithoutDescriptions.new("app") { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.template = ENV['template'] if ENV['template']
......
......@@ -183,9 +183,6 @@ def test_config_jdbcmysql_database
run_generator([destination_root, "-d", "jdbcmysql"])
assert_file "config/database.yml", /mysql/
assert_gem "activerecord-jdbcmysql-adapter"
# TODO: When the JRuby guys merge jruby-openssl in
# jruby this will be removed
assert_gem "jruby-openssl" if defined?(JRUBY_VERSION)
end
def test_config_jdbcsqlite3_database
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册