From b7b97fadc183771b129a7b11b7b759f72bfb2dd3 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 22 Jul 2012 13:26:43 -0500 Subject: add :nodoc: directive to AM::ObserverArray internal methods [ci skip] --- activemodel/lib/active_model/observer_array.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb index 8de6918d18..2a522e6f18 100644 --- a/activemodel/lib/active_model/observer_array.rb +++ b/activemodel/lib/active_model/observer_array.rb @@ -18,7 +18,7 @@ module ActiveModel # Disables one or more observers. This supports multiple forms: # # ORM.observers.disable :all - # # => disables all observers for all models subclassed from + # # => disables all observers for all models subclassed from # # an ORM base class that includes ActiveModel::Observing # # e.g. ActiveRecord::Base # @@ -43,7 +43,7 @@ module ActiveModel # Enables one or more observers. This supports multiple forms: # # ORM.observers.enable :all - # # => enables all observers for all models subclassed from + # # => enables all observers for all models subclassed from # # an ORM base class that includes ActiveModel::Observing # # e.g. ActiveRecord::Base # @@ -71,11 +71,11 @@ module ActiveModel protected - def disabled_observers + def disabled_observers #:nodoc: @disabled_observers ||= Set.new end - def observer_class_for(observer) + def observer_class_for(observer) #:nodoc: return observer if observer.is_a?(Class) if observer.respond_to?(:to_sym) # string/symbol @@ -86,25 +86,25 @@ module ActiveModel end end - def start_transaction + def start_transaction #:nodoc: disabled_observer_stack.push(disabled_observers.dup) each_subclass_array do |array| array.start_transaction end end - def disabled_observer_stack + def disabled_observer_stack #:nodoc: @disabled_observer_stack ||= [] end - def end_transaction + def end_transaction #:nodoc: @disabled_observers = disabled_observer_stack.pop each_subclass_array do |array| array.end_transaction end end - def transaction + def transaction #:nodoc: start_transaction begin @@ -114,13 +114,13 @@ module ActiveModel end end - def each_subclass_array + def each_subclass_array #:nodoc: model_class.descendants.each do |subclass| yield subclass.observers end end - def set_enablement(enabled, observers) + def set_enablement(enabled, observers) #:nodoc: if block_given? transaction do set_enablement(enabled, observers) -- cgit v1.2.3 From c12024bc7dabb3d911acf49c0c936541ff5f8e93 Mon Sep 17 00:00:00 2001 From: dm1try Date: Sun, 22 Jul 2012 23:47:30 +0300 Subject: tiny mistake in description --- guides/source/configuring.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile index cd9aab4892..e7272a51b7 100644 --- a/guides/source/configuring.textile +++ b/guides/source/configuring.textile @@ -157,7 +157,7 @@ Rails 3.1, by default, is set up to use the +sprockets+ gem to manage assets wit * +config.assets.digest+ enables the use of MD5 fingerprints in asset names. Set to +true+ by default in +production.rb+. -* +config.assets.debug+ disables the concatenation and compression of assets. Set to +false+ by default in +development.rb+. +* +config.assets.debug+ disables the concatenation and compression of assets. Set to +true+ by default in +development.rb+. * +config.assets.manifest+ defines the full path to be used for the asset precompiler's manifest file. Defaults to using +config.assets.prefix+. -- cgit v1.2.3 From 890b9dd4439986e306ec4fc0067a00effa606204 Mon Sep 17 00:00:00 2001 From: Weston Platter Date: Sun, 22 Jul 2012 17:24:49 -0400 Subject: added 2 strategies for extending engine models --- guides/source/engines.textile | 79 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/guides/source/engines.textile b/guides/source/engines.textile index 53c2845731..db23c1c584 100644 --- a/guides/source/engines.textile +++ b/guides/source/engines.textile @@ -657,6 +657,84 @@ h3. Improving engine functionality This section looks at overriding or adding functionality to the views, controllers and models provided by an engine. +h4. Overriding Models + +Engine Models can be extended by (1) implementing decorators, or (2) including modules. + +h5. Decorators + +Decorators extends Engine's model classes in the main application by open classing Engine models at run time execution. + + +# MyApp/app/decorators/models/blorgh/post_decorator.rb + +Blorgh::Post.class_eval do + def time_since_created + Time.current - created_at + end +end + + +h5. Modules + +The other strategy is to create modules within the Engine holding all the models' code and include these in the respective Engine's model classes. Thus the Engine's model classes contain a mere include line referencing the respective module. + +Engine models can be overriden in the main application by creating a file with the Engine's same namespace and including the module originally referenced in the Engine's model class. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage the correct ordering of module dependencies at run time (it's worth it to reach the linked documentation). + + +# MyApp/app/models/blorgh/post.rb +# overrides Blorgh's original Post model + +class Blorgh::Post < ActiveRecord::Base + include Blorgh::Concerns::Models::Post + + def time_since_created + Time.current - created_at + end +end + + +# Blorgh/app/models/post.rb +# this class is overriden by the MyApp Post model + +class Post < ActiveRecord::Base + include Blorgh::Concerns::Models::Post +end + + +# Blorgh/app/concerns/models/post + +module Blorg::Concerns::Models::Post + extend ActiveSupport::Concern + + # 'included do' causes the code within to be evaluated in the conext + # where it is included, rather be executed in the module's context. + included do + attr_accessor :author_name + belongs_to :author, :class_name => "User" + + before_save :set_author + + private + + def set_author + self.author = User.find_or_create_by_name(author_name) + end + end + + # methods defined here will be instance methods by default + def some_method + 'some method string' + end + + module ClassMethods + def some_class_method + 'some class method string' + end + end +end + + h4. Overriding views When Rails looks for a view to render, it will first look in the +app/views+ directory of the application. If it cannot find the view there, then it will check in the +app/views+ directories of all engines which have this directory. @@ -772,7 +850,6 @@ s.add_dependency "moo" To specify a dependency that should only be installed as a development dependency of the application, specify it like this: - s.add_development_dependency "moo" -- cgit v1.2.3 From 738a0e17eb2f7b6656e8a4a9fa58d4609bcc7eaa Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 22 Jul 2012 19:51:17 -0500 Subject: fix removed ruby tag in commit 890b9dd [ci skip] --- guides/source/engines.textile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/guides/source/engines.textile b/guides/source/engines.textile index db23c1c584..11c837be32 100644 --- a/guides/source/engines.textile +++ b/guides/source/engines.textile @@ -706,17 +706,17 @@ end module Blorg::Concerns::Models::Post extend ActiveSupport::Concern - + # 'included do' causes the code within to be evaluated in the conext # where it is included, rather be executed in the module's context. included do attr_accessor :author_name belongs_to :author, :class_name => "User" - + before_save :set_author - + private - + def set_author self.author = User.find_or_create_by_name(author_name) end @@ -850,6 +850,7 @@ s.add_dependency "moo" To specify a dependency that should only be installed as a development dependency of the application, specify it like this: + s.add_development_dependency "moo" -- cgit v1.2.3 From c34c1916d1d6cd6ba219aa39eb97fa2e77c4c61f Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 23 Jul 2012 04:13:18 -0400 Subject: Removed reference to composed_of. It was previously removed from the code, so we shouldn't mention it in the docs --- activerecord/lib/active_record/sanitization.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index ca767cc704..0dd4070ba4 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -54,9 +54,6 @@ module ActiveRecord # # => "`other_records`.`id` = 7" # { :other_records => { :id => 7 } } # # => "`other_records`.`id` = 7" - # And for value objects on a composed_of relationship: - # { :address => Address.new("123 abc st.", "chicago") } - # # => "address_street='123 abc st.' and address_city='chicago'" def sanitize_sql_hash_for_conditions(attrs, default_table_name = self.table_name) table = Arel::Table.new(table_name).alias(default_table_name) PredicateBuilder.build_from_hash(arel_engine, attrs, table).map { |b| -- cgit v1.2.3 From c74ff7f73b9505478cec6eff20f1030a61285cd8 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Tue, 24 Jul 2012 13:13:14 -0500 Subject: Update performance testing guide [ci skip] * Update test templates. * Remove some 1.8 references. * Update guide format to be easier for contributors. --- guides/source/performance_testing.textile | 230 ++++++++++++++++++++---------- 1 file changed, 152 insertions(+), 78 deletions(-) diff --git a/guides/source/performance_testing.textile b/guides/source/performance_testing.textile index 982fd1b070..b7d4f1ef33 100644 --- a/guides/source/performance_testing.textile +++ b/guides/source/performance_testing.textile @@ -1,40 +1,55 @@ h2. Performance Testing Rails Applications -This guide covers the various ways of performance testing a Ruby on Rails application. By referring to this guide, you will be able to: - -* Understand the various types of benchmarking and profiling metrics -* Generate performance and benchmarking tests -* Install and use a GC-patched Ruby binary to measure memory usage and object allocation -* Understand the benchmarking information provided by Rails inside the log files -* Learn about various tools facilitating benchmarking and profiling - -Performance testing is an integral part of the development cycle. It is very important that you don't make your end users wait for too long before the page is completely loaded. Ensuring a pleasant browsing experience for end users and cutting the cost of unnecessary hardware is important for any non-trivial web application. +This guide covers the various ways of performance testing a Ruby on Rails +application. By referring to this guide, you will be able to: + +* Understand the various types of benchmarking and profiling metrics. +* Generate performance and benchmarking tests. +* Install and use a GC-patched Ruby binary to measure memory usage and object + allocation. +* Understand the benchmarking information provided by Rails inside the log files. +* Learn about various tools facilitating benchmarking and profiling. + +Performance testing is an integral part of the development cycle. It is very +important that you don't make your end users wait for too long before the page +is completely loaded. Ensuring a pleasant browsing experience for end users and +cutting the cost of unnecessary hardware is important for any non-trivial web +application. endprologue. h3. Performance Test Cases -Rails performance tests are a special type of integration tests, designed for benchmarking and profiling the test code. With performance tests, you can determine where your application's memory or speed problems are coming from, and get a more in-depth picture of those problems. +Rails performance tests are a special type of integration tests, designed for +benchmarking and profiling the test code. With performance tests, you can +determine where your application's memory or speed problems are coming from, +and get a more in-depth picture of those problems. -In a freshly generated Rails application, +test/performance/browsing_test.rb+ contains an example of a performance test: +In a freshly generated Rails application, +test/performance/browsing_test.rb+ +contains an example of a performance test: require 'test_helper' require 'rails/performance_test_help' -# Profiling results for each test method are written to tmp/performance. class BrowsingTest < ActionDispatch::PerformanceTest - def test_homepage + # Refer to the documentation for all available options + # self.profile_options = { runs: 5, metrics: [:wall_time, :memory], + # output: 'tmp/performance', formats: [:flat] } + + test "homepage" do get '/' end end -This example is a simple performance test case for profiling a GET request to the application's homepage. +This example is a simple performance test case for profiling a GET request to +the application's homepage. h4. Generating Performance Tests -Rails provides a generator called +performance_test+ for creating new performance tests: +Rails provides a generator called +performance_test+ for creating new +performance tests: $ rails generate performance_test homepage @@ -47,8 +62,11 @@ require 'test_helper' require 'rails/performance_test_help' class HomepageTest < ActionDispatch::PerformanceTest - # Replace this with your real tests. - def test_homepage + # Refer to the documentation for all available options + # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory], + # :output => 'tmp/performance', :formats => [:flat] } + + test "homepage" do get '/' end end @@ -60,7 +78,7 @@ Let's assume your application has the following controller and model: # routes.rb -root :to => 'home#index' +root to: 'home#dashboard' resources :posts # home_controller.rb @@ -97,9 +115,11 @@ end h5. Controller Example -Because performance tests are a special kind of integration test, you can use the +get+ and +post+ methods in them. +Because performance tests are a special kind of integration test, you can use +the +get+ and +post+ methods in them. -Here's the performance test for +HomeController#dashboard+ and +PostsController#create+: +Here's the performance test for +HomeController#dashboard+ and ++PostsController#create+: require 'test_helper' @@ -111,21 +131,24 @@ class PostPerformanceTest < ActionDispatch::PerformanceTest login_as(:lifo) end - def test_homepage + test "homepage" do get '/dashboard' end - def test_creating_new_post - post '/posts', :post => { :body => 'lifo is fooling you' } + test "creating new post" do + post '/posts', post: { body: 'lifo is fooling you' } end end -You can find more details about the +get+ and +post+ methods in the "Testing Rails Applications":testing.html guide. +You can find more details about the +get+ and +post+ methods in the +"Testing Rails Applications":testing.html guide. h5. Model Example -Even though the performance tests are integration tests and hence closer to the request/response cycle by nature, you can still performance test pure model code. +Even though the performance tests are integration tests and hence closer to +the request/response cycle by nature, you can still performance test pure model +code. Performance test for +Post+ model: @@ -134,11 +157,11 @@ require 'test_helper' require 'rails/performance_test_help' class PostModelTest < ActionDispatch::PerformanceTest - def test_creation - Post.create :body => 'still fooling you', :cost => '100' + test "creation" do + Post.create body: 'still fooling you', cost: '100' end - def test_slow_method + test "slow method" do # Using posts(:awesome) fixture posts(:awesome).slow_method end @@ -151,7 +174,8 @@ Performance tests can be run in two modes: Benchmarking and Profiling. h5. Benchmarking -Benchmarking makes it easy to quickly gather a few metrics about each test run. By default, each test case is run *4 times* in benchmarking mode. +Benchmarking makes it easy to quickly gather a few metrics about each test run. +By default, each test case is run *4 times* in benchmarking mode. To run performance tests in benchmarking mode: @@ -161,7 +185,10 @@ $ rake test:benchmark h5. Profiling -Profiling allows you to make an in-depth analysis of each of your tests by using an external profiler. Depending on your Ruby interpreter, this profiler can be native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each test case is run *once* in profiling mode. +Profiling allows you to make an in-depth analysis of each of your tests by using +an external profiler. Depending on your Ruby interpreter, this profiler can be +native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each +test case is run *once* in profiling mode. To run performance tests in profiling mode: @@ -171,23 +198,33 @@ $ rake test:profile h4. Metrics -Benchmarking and profiling run performance tests and give you multiple metrics. The availability of each metric is determined by the interpreter being used—none of them support all metrics—and by the mode in use. A brief description of each metric and their availability across interpreters/modes is given below. +Benchmarking and profiling run performance tests and give you multiple metrics. +The availability of each metric is determined by the interpreter being used—none +of them support all metrics—and by the mode in use. A brief description of each +metric and their availability across interpreters/modes is given below. h5. Wall Time -Wall time measures the real world time elapsed during the test run. It is affected by any other processes concurrently running on the system. +Wall time measures the real world time elapsed during the test run. It is +affected by any other processes concurrently running on the system. h5. Process Time -Process time measures the time taken by the process. It is unaffected by any other processes running concurrently on the same system. Hence, process time is likely to be constant for any given performance test, irrespective of the machine load. +Process time measures the time taken by the process. It is unaffected by any +other processes running concurrently on the same system. Hence, process time +is likely to be constant for any given performance test, irrespective of the +machine load. h5. CPU Time -Similar to process time, but leverages the more accurate CPU clock counter available on the Pentium and PowerPC platforms. +Similar to process time, but leverages the more accurate CPU clock counter +available on the Pentium and PowerPC platforms. h5. User Time -User time measures the amount of time the CPU spent in user-mode, i.e. within the process. This is not affected by other processes and by the time it possibly spends blocked. +User time measures the amount of time the CPU spent in user-mode, i.e. within +the process. This is not affected by other processes and by the time it possibly +spends blocked. h5. Memory @@ -223,11 +260,13 @@ h6(#profiling_1). Profiling |_.Rubinius | yes | no | no | no | no | no | no | no | |_.JRuby | yes | no | no | no | no | no | no | no | -NOTE: To profile under JRuby you'll need to run +export JRUBY_OPTS="-Xlaunch.inproc=false --profile.api"+ *before* the performance tests. +NOTE: To profile under JRuby you'll need to run +export JRUBY_OPTS="-Xlaunch.inproc=false --profile.api"+ +*before* the performance tests. h4. Understanding the Output -Performance tests generate different outputs inside +tmp/performance+ directory depending on their mode and metric. +Performance tests generate different outputs inside +tmp/performance+ directory +depending on their mode and metric. h5(#output-benchmarking). Benchmarking @@ -248,7 +287,9 @@ BrowsingTest#test_homepage (31 ms warmup) h6. CSV Files -Performance test results are also appended to +.csv+ files inside +tmp/performance+. For example, running the default +BrowsingTest#test_homepage+ will generate following five files: +Performance test results are also appended to +.csv+ files inside +tmp/performance+. +For example, running the default +BrowsingTest#test_homepage+ will generate +following five files: * BrowsingTest#test_homepage_gc_runs.csv * BrowsingTest#test_homepage_gc_time.csv @@ -256,7 +297,9 @@ Performance test results are also appended to +.csv+ files inside +tmp/performan * BrowsingTest#test_homepage_objects.csv * BrowsingTest#test_homepage_wall_time.csv -As the results are appended to these files each time the performance tests are run in benchmarking mode, you can collect data over a period of time. This can be very helpful in analyzing the effects of code changes. +As the results are appended to these files each time the performance tests are +run in benchmarking mode, you can collect data over a period of time. This can +be very helpful in analyzing the effects of code changes. Sample output of +BrowsingTest#test_homepage_wall_time.csv+: @@ -276,7 +319,10 @@ measurement,created_at,app,rails,ruby,platform h5(#output-profiling). Profiling -In profiling mode, performance tests can generate multiple types of outputs. The command line output is always presented but support for the others is dependent on the interpreter in use. A brief description of each type and their availability across interpreters is given below. +In profiling mode, performance tests can generate multiple types of outputs. +The command line output is always presented but support for the others is +dependent on the interpreter in use. A brief description of each type and +their availability across interpreters is given below. h6. Command Line @@ -291,15 +337,18 @@ BrowsingTest#test_homepage (58 ms warmup) h6. Flat -Flat output shows the metric—time, memory, etc—measure in each method. "Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/flat_txt.html. +Flat output shows the metric—time, memory, etc—measure in each method. +"Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/flat_txt.html. h6. Graph -Graph output shows the metric measure in each method, which methods call it and which methods it calls. "Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/graph_txt.html. +Graph output shows the metric measure in each method, which methods call it and +which methods it calls. "Check Ruby-Prof documentation for a better explanation":http://ruby-prof.rubyforge.org/files/examples/graph_txt.html. h6. Tree -Tree output is profiling information in calltree format for use by "kcachegrind":http://kcachegrind.sourceforge.net/html/Home.html and similar tools. +Tree output is profiling information in calltree format for use by "kcachegrind":http://kcachegrind.sourceforge.net/html/Home.html +and similar tools. h6. Output Availability @@ -311,24 +360,24 @@ h6. Output Availability h4. Tuning Test Runs -Test runs can be tuned by setting the +profile_options+ class variable on your test class. +Test runs can be tuned by setting the +profile_options+ class variable on your +test class. require 'test_helper' require 'rails/performance_test_help' -# Profiling results for each test method are written to tmp/performance. class BrowsingTest < ActionDispatch::PerformanceTest - self.profile_options = { :runs => 5, - :metrics => [:wall_time, :memory] } + self.profile_options = { runs: 5, metrics: [:wall_time, :memory] } - def test_homepage + test "homepage" get '/' end end -In this example, the test would run 5 times and measure wall time and memory. There are a few configurable options: +In this example, the test would run 5 times and measure wall time and memory. +There are a few configurable options: |_.Option |_.Description|_.Default|_.Mode| |+:runs+ |Number of runs.|Benchmarking: 4, Profiling: 1|Both| @@ -346,11 +395,13 @@ Metrics and formats have different defaults depending on the interpreter in use. |/2.JRuby |Benchmarking|+[:wall_time, :user_time, :memory, :gc_runs, :gc_time]+|N/A| |Profiling |+[:wall_time]+|+[:flat, :graph]+| -As you've probably noticed by now, metrics and formats are specified using a symbol array with each name "underscored.":http://api.rubyonrails.org/classes/String.html#method-i-underscore +As you've probably noticed by now, metrics and formats are specified using a +symbol array with each name "underscored.":http://api.rubyonrails.org/classes/String.html#method-i-underscore h4. Performance Test Environment -Performance tests are run in the +test+ environment. But running performance tests will set the following configuration parameters: +Performance tests are run in the +test+ environment. But running performance +tests will set the following configuration parameters: ActionController::Base.perform_caching = true @@ -358,11 +409,13 @@ ActiveSupport::Dependencies.mechanism = :require Rails.logger.level = ActiveSupport::BufferedLogger::INFO -As +ActionController::Base.perform_caching+ is set to +true+, performance tests will behave much as they do in the +production+ environment. +As +ActionController::Base.perform_caching+ is set to +true+, performance tests +will behave much as they do in the +production+ environment. h4. Installing GC-Patched MRI -To get the best from Rails' performance tests under MRI, you'll need to build a special Ruby binary with some super powers. +To get the best from Rails' performance tests under MRI, you'll need to build +a special Ruby binary with some super powers. The recommended patches for each MRI version are: @@ -371,13 +424,18 @@ The recommended patches for each MRI version are: |1.8.7|ruby187gc| |1.9.2 and above|gcdata| -All of these can be found on "RVM's _patches_ directory":https://github.com/wayneeseguin/rvm/tree/master/patches/ruby under each specific interpreter version. +All of these can be found on "RVM's _patches_ directory":https://github.com/wayneeseguin/rvm/tree/master/patches/ruby +under each specific interpreter version. -Concerning the installation itself, you can either do this easily by using "RVM":http://rvm.beginrescueend.com or you can build everything from source, which is a little bit harder. +Concerning the installation itself, you can either do this easily by using +"RVM":http://rvm.beginrescueend.com or you can build everything from source, +which is a little bit harder. h5. Install Using RVM -The process of installing a patched Ruby interpreter is very easy if you let RVM do the hard work. All of the following RVM commands will provide you with a patched Ruby interpreter: +The process of installing a patched Ruby interpreter is very easy if you let RVM +do the hard work. All of the following RVM commands will provide you with a +patched Ruby interpreter: $ rvm install 1.9.2-p180 --patch gcdata @@ -385,7 +443,8 @@ $ rvm install 1.8.7 --patch ruby187gc $ rvm install 1.9.2-p180 --patch ~/Downloads/downloaded_gcdata_patch.patch -You can even keep your regular interpreter by assigning a name to the patched one: +You can even keep your regular interpreter by assigning a name to the patched +one: $ rvm install 1.9.2-p180 --patch gcdata --name gcdata @@ -397,7 +456,9 @@ And it's done! You have installed a patched Ruby interpreter. h5. Install From Source -This process is a bit more complicated, but straightforward nonetheless. If you've never compiled a Ruby binary before, follow these steps to build a Ruby binary inside your home directory. +This process is a bit more complicated, but straightforward nonetheless. If +you've never compiled a Ruby binary before, follow these steps to build a +Ruby binary inside your home directory. h6. Download and Extract @@ -417,7 +478,9 @@ $ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.8.7/ruby187g h6. Configure and Install -The following will install Ruby in your home directory's +/rubygc+ directory. Make sure to replace +<homedir>+ with a full patch to your actual home directory. +The following will install Ruby in your home directory's +/rubygc+ directory. +Make sure to replace +<homedir>+ with a full patch to your actual home +directory. $ ./configure --prefix=//rubygc @@ -438,23 +501,22 @@ alias gcrails='~/rubygc/bin/rails' Don't forget to use your aliases from now on. -h6. Install RubyGems (1.8 only!) - -Download "RubyGems":http://rubyforge.org/projects/rubygems and install it from source. Rubygem's README file should have necessary installation instructions. Please note that this step isn't necessary if you've installed Ruby 1.9 and above. - h4. Using Ruby-Prof on MRI and REE -Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile under MRI or REE: +Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile +under MRI or REE: -gem 'ruby-prof', :git => 'git://github.com/wycats/ruby-prof.git' +gem 'ruby-prof', git: 'git://github.com/wycats/ruby-prof.git' Now run +bundle install+ and you're ready to go. h3. Command Line Tools -Writing performance test cases could be an overkill when you are looking for one time tests. Rails ships with two command line tools that enable quick and dirty performance testing: +Writing performance test cases could be an overkill when you are looking for one +time tests. Rails ships with two command line tools that enable quick and dirty +performance testing: h4. +benchmarker+ @@ -498,11 +560,14 @@ Example: $ rails profiler 'Item.all' 'CouchItem.all' --runs 2 --metrics process_time --formats flat -NOTE: Metrics and formats vary from interpreter to interpreter. Pass +--help+ to each tool to see the defaults for your interpreter. +NOTE: Metrics and formats vary from interpreter to interpreter. Pass +--help+ to +each tool to see the defaults for your interpreter. h3. Helper Methods -Rails provides various helper methods inside Active Record, Action Controller and Action View to measure the time taken by a given piece of code. The method is called +benchmark()+ in all the three components. +Rails provides various helper methods inside Active Record, Action Controller +and Action View to measure the time taken by a given piece of code. The method +is called +benchmark()+ in all the three components. h4. Model @@ -514,17 +579,19 @@ Project.benchmark("Creating project") do end -This benchmarks the code enclosed in the +Project.benchmark("Creating project") do...end+ block and prints the result to the log file: +This benchmarks the code enclosed in the +Project.benchmark("Creating project") do...end+ +block and prints the result to the log file: Creating project (185.3ms) -Please refer to the "API docs":http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M001336 for additional options to +benchmark()+ +Please refer to the "API docs":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark +for additional options to +benchmark()+. h4. Controller -Similarly, you could use this helper method inside "controllers":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html +Similarly, you could use this helper method inside "controllers.":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html def process_projects @@ -535,7 +602,7 @@ def process_projects end -NOTE: +benchmark+ is a class method inside controllers +NOTE: +benchmark+ is a class method inside controllers. h4. View @@ -549,7 +616,8 @@ And in "views":http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.ht h3. Request Logging -Rails log files contain very useful information about the time taken to serve each request. Here's a typical log file entry: +Rails log files contain very useful information about the time taken to serve +each request. Here's a typical log file entry: Processing ItemsController#index (for 127.0.0.1 at 2009-01-08 03:06:39) [GET] @@ -564,9 +632,14 @@ For this section, we're only interested in the last line: Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items] -This data is fairly straightforward to understand. Rails uses millisecond(ms) as the metric to measure the time taken. The complete request spent 5 ms inside Rails, out of which 2 ms were spent rendering views and none was spent communication with the database. It's safe to assume that the remaining 3 ms were spent inside the controller. +This data is fairly straightforward to understand. Rails uses millisecond(ms) as +the metric to measure the time taken. The complete request spent 5 ms inside +Rails, out of which 2 ms were spent rendering views and none was spent +communication with the database. It's safe to assume that the remaining 3 ms +were spent inside the controller. -Michael Koziarski has an "interesting blog post":http://www.therailsway.com/2009/1/6/requests-per-second explaining the importance of using milliseconds as the metric. +Michael Koziarski has an "interesting blog post":http://www.therailsway.com/2009/1/6/requests-per-second +explaining the importance of using milliseconds as the metric. h3. Useful Links @@ -587,11 +660,12 @@ h4. Generic Tools h4. Tutorials and Documentation * "ruby-prof API Documentation":http://ruby-prof.rubyforge.org -* "Request Profiling Railscast":http://railscasts.com/episodes/98-request-profiling - Outdated, but useful for understanding call graphs +* "Request Profiling Railscast":http://railscasts.com/episodes/98-request-profiling - Outdated, but useful for understanding call graphs. h3. Commercial Products -Rails has been lucky to have a few companies dedicated to Rails-specific performance tools. A couple of those are: +Rails has been lucky to have a few companies dedicated to Rails-specific +performance tools. A couple of those are: * "New Relic":http://www.newrelic.com -* "Scout":http://scoutapp.com +* "Scout":http://scoutapp.com \ No newline at end of file -- cgit v1.2.3 From 46b24c958a89b75e48ee42be0520a15b7c4484a9 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Fri, 27 Jul 2012 12:59:05 -0500 Subject: use 'HTTP_AUTHORIZATION' instead of :authorization as key when dealing with HTTP Token authentication in integration tests --- actionpack/lib/action_controller/metal/http_authentication.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 0050ede806..b1c3100837 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -372,7 +372,7 @@ module ActionController # def test_access_granted_from_xml # get( # "/notes/1.xml", nil, - # :authorization => ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) + # 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) # ) # # assert_equal 200, status -- cgit v1.2.3 From 74262e654b56e8b95e8e1af46d73e3f89a8df93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 27 Jul 2012 19:36:44 -0300 Subject: Revert "Removed reference to composed_of." This reverts commit c34c1916d1d6cd6ba219aa39eb97fa2e77c4c61f. Reason: composed_of was added from now to discuss better --- activerecord/lib/active_record/sanitization.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 0dd4070ba4..ca767cc704 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -54,6 +54,9 @@ module ActiveRecord # # => "`other_records`.`id` = 7" # { :other_records => { :id => 7 } } # # => "`other_records`.`id` = 7" + # And for value objects on a composed_of relationship: + # { :address => Address.new("123 abc st.", "chicago") } + # # => "address_street='123 abc st.' and address_city='chicago'" def sanitize_sql_hash_for_conditions(attrs, default_table_name = self.table_name) table = Arel::Table.new(table_name).alias(default_table_name) PredicateBuilder.build_from_hash(arel_engine, attrs, table).map { |b| -- cgit v1.2.3 From 03404936945b452b8e66e53e183973176dae8301 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Fri, 27 Jul 2012 21:02:08 -0500 Subject: update to_param docs [ci skip] --- activesupport/lib/active_support/core_ext/object/to_param.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb index e5f81078ee..0d5f3501e5 100644 --- a/activesupport/lib/active_support/core_ext/object/to_param.rb +++ b/activesupport/lib/active_support/core_ext/object/to_param.rb @@ -6,18 +6,21 @@ class Object end class NilClass + # Returns +self+. def to_param self end end class TrueClass + # Returns +self+. def to_param self end end class FalseClass + # Returns +self+. def to_param self end @@ -35,12 +38,12 @@ class Hash # Returns a string representation of the receiver suitable for use as a URL # query string: # - # {:name => 'David', :nationality => 'Danish'}.to_param + # {name: 'David', nationality: 'Danish'}.to_param # # => "name=David&nationality=Danish" # # An optional namespace can be passed to enclose the param names: # - # {:name => 'David', :nationality => 'Danish'}.to_param('user') + # {name: 'David', nationality: 'Danish'}.to_param('user') # # => "user[name]=David&user[nationality]=Danish" # # The string pairs "key=value" that conform the query string -- cgit v1.2.3 From 36ebafdce959a2cf70f10655df46237020f3270a Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Fri, 27 Jul 2012 23:16:51 -0500 Subject: fix AM::Naming examples [ci skip] --- activemodel/lib/active_model/naming.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index ea4f9341c6..43d11b1b08 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -256,11 +256,11 @@ module ActiveModel # Returns string to use while generating route names. It differs for # namespaced models regarding whether it's inside isolated engine. # - # For isolated engine: - # ActiveModel::Naming.route_key(Blog::Post) #=> post + # # For isolated engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> post # - # For shared engine: - # ActiveModel::Naming.route_key(Blog::Post) #=> blog_post + # # For shared engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> blog_post def self.singular_route_key(record_or_class) model_name_from_record_or_class(record_or_class).singular_route_key end @@ -268,11 +268,11 @@ module ActiveModel # Returns string to use while generating route names. It differs for # namespaced models regarding whether it's inside isolated engine. # - # For isolated engine: - # ActiveModel::Naming.route_key(Blog::Post) #=> posts + # # For isolated engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> posts # - # For shared engine: - # ActiveModel::Naming.route_key(Blog::Post) #=> blog_posts + # # For shared engine: + # ActiveModel::Naming.route_key(Blog::Post) #=> blog_posts # # The route key also considers if the noun is uncountable and, in # such cases, automatically appends _index. @@ -283,11 +283,11 @@ module ActiveModel # Returns string to use for params names. It differs for # namespaced models regarding whether it's inside isolated engine. # - # For isolated engine: - # ActiveModel::Naming.param_key(Blog::Post) #=> post + # # For isolated engine: + # ActiveModel::Naming.param_key(Blog::Post) #=> post # - # For shared engine: - # ActiveModel::Naming.param_key(Blog::Post) #=> blog_post + # # For shared engine: + # ActiveModel::Naming.param_key(Blog::Post) #=> blog_post def self.param_key(record_or_class) model_name_from_record_or_class(record_or_class).param_key end -- cgit v1.2.3 From b8e4f7155b9c06842f1d9d17f36886cb663aa3a4 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Fri, 27 Jul 2012 23:38:34 -0500 Subject: add example to ActiveModel::Naming#model_name [ci skip] --- activemodel/lib/active_model/naming.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 43d11b1b08..30d2da9af7 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -220,6 +220,14 @@ module ActiveModel # Returns an ActiveModel::Name object for module. It can be # used to retrieve all kinds of naming-related information # (See ActiveModel::Name for more information). + # + # class Person < ActiveModel::Model + # end + # + # Person.model_name # => Person + # Person.model_name.class # => ActiveModel::Name + # Person.model_name.singular # => "person" + # Person.model_name.plural # => "people" def model_name @_model_name ||= begin namespace = self.parents.detect do |n| -- cgit v1.2.3 From ac18d642e9282fad0c2ba8f16d3c9627b507b40f Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sat, 28 Jul 2012 00:58:21 -0500 Subject: update ActiveModel::MassAssignmentSecurity docs [ci skip] --- .../lib/active_model/mass_assignment_security.rb | 242 +++++++++++++++------ 1 file changed, 177 insertions(+), 65 deletions(-) diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index e57fcf1610..540b90c4cc 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -5,6 +5,47 @@ require 'active_model/mass_assignment_security/sanitizer' module ActiveModel # = Active Model Mass-Assignment Security + # + # Mass assignment security provides an interface for protecting attributes + # from end-user assignment. For more complex permissions, mass assignment + # security may be handled outside the model by extending a non-ActiveRecord + # class, such as a controller, with this behavior. + # + # For example, a logged in user may need to assign additional attributes + # depending on their role: + # + # class AccountsController < ApplicationController + # include ActiveModel::MassAssignmentSecurity + # + # attr_accessible :first_name, :last_name + # attr_accessible :first_name, :last_name, :plan_id, as: :admin + # + # def update + # ... + # @account.update_attributes(account_params) + # ... + # end + # + # protected + # + # def account_params + # role = admin ? :admin : :default + # sanitize_for_mass_assignment(params[:account], role) + # end + # + # end + # + # = Configuration options + # + # * mass_assignment_sanitizer - Defines sanitize method. Possible + # values are: + # * :logger (default) - writes filtered attributes to logger + # * :strict - raise ActiveModel::MassAssignmentSecurity::Error + # on any protected attribute update. + # + # You can specify your own sanitizer object eg. MySanitizer.new. + # See ActiveModel::MassAssignmentSecurity::LoggerSanitizer for + # example implementation. module MassAssignmentSecurity extend ActiveSupport::Concern @@ -17,55 +58,17 @@ module ActiveModel self.mass_assignment_sanitizer = :logger end - # Mass assignment security provides an interface for protecting attributes - # from end-user assignment. For more complex permissions, mass assignment security - # may be handled outside the model by extending a non-ActiveRecord class, - # such as a controller, with this behavior. - # - # For example, a logged in user may need to assign additional attributes depending - # on their role: - # - # class AccountsController < ApplicationController - # include ActiveModel::MassAssignmentSecurity - # - # attr_accessible :first_name, :last_name - # attr_accessible :first_name, :last_name, :plan_id, :as => :admin - # - # def update - # ... - # @account.update_attributes(account_params) - # ... - # end - # - # protected - # - # def account_params - # role = admin ? :admin : :default - # sanitize_for_mass_assignment(params[:account], role) - # end - # - # end - # - # = Configuration options - # - # * mass_assignment_sanitizer - Defines sanitize method. Possible values are: - # * :logger (default) - writes filtered attributes to logger - # * :strict - raise ActiveModel::MassAssignmentSecurity::Error on any protected attribute update - # - # You can specify your own sanitizer object eg. MySanitizer.new. - # See ActiveModel::MassAssignmentSecurity::LoggerSanitizer for example implementation. - # - # module ClassMethods # Attributes named in this macro are protected from mass-assignment # whenever attributes are sanitized before assignment. A role for the - # attributes is optional, if no role is provided then :default is used. - # A role can be defined by using the :as option with a symbol or an array of symbols as the value. + # attributes is optional, if no role is provided then :default + # is used. A role can be defined by using the :as option with a + # symbol or an array of symbols as the value. # # Mass-assignment to these attributes will simply be ignored, to assign # to them you can use direct writer methods. This is meant to protect # sensitive attributes from being overwritten by malicious users - # tampering with URLs or forms. Example: + # tampering with URLs or forms. # # class Customer # include ActiveModel::MassAssignmentSecurity @@ -74,7 +77,7 @@ module ActiveModel # # attr_protected :logins_count # # Suppose that admin can not change email for customer - # attr_protected :logins_count, :email, :as => :admin + # attr_protected :logins_count, :email, as: :admin # # def assign_attributes(values, options = {}) # sanitize_for_mass_assignment(values, options[:as]).each do |k, v| @@ -83,23 +86,23 @@ module ActiveModel # end # end # - # When using the :default role: + # When using the :default role: # # customer = Customer.new - # customer.assign_attributes({ "name" => "David", "email" => "a@b.com", :logins_count => 5 }, :as => :default) - # customer.name # => "David" - # customer.email # => "a@b.com" - # customer.logins_count # => nil + # customer.assign_attributes({ name: 'David', email: 'a@b.com', logins_count: 5 }, as: :default) + # customer.name # => "David" + # customer.email # => "a@b.com" + # customer.logins_count # => nil # - # And using the :admin role: + # And using the :admin role: # # customer = Customer.new - # customer.assign_attributes({ "name" => "David", "email" => "a@b.com", :logins_count => 5}, :as => :admin) - # customer.name # => "David" - # customer.email # => nil - # customer.logins_count # => nil + # customer.assign_attributes({ name: 'David', email: 'a@b.com', logins_count: 5}, as: :admin) + # customer.name # => "David" + # customer.email # => nil + # customer.logins_count # => nil # - # customer.email = "c@d.com" + # customer.email = 'c@d.com' # customer.email # => "c@d.com" # # To start from an all-closed default and enable attributes as needed, @@ -125,8 +128,9 @@ module ActiveModel # mass-assignment. # # Like +attr_protected+, a role for the attributes is optional, - # if no role is provided then :default is used. A role can be defined by - # using the :as option with a symbol or an array of symbols as the value. + # if no role is provided then :default is used. A role can be + # defined by using the :as option with a symbol or an array of + # symbols as the value. # # This is the opposite of the +attr_protected+ macro: Mass-assignment # will only set attributes in this list, to assign to the rest of @@ -142,9 +146,9 @@ module ActiveModel # attr_accessor :name, :credit_rating # # # Both admin and default user can change name of a customer - # attr_accessible :name, :as => [:admin, :default] + # attr_accessible :name, as: [:admin, :default] # # Only admin can change credit rating of a customer - # attr_accessible :credit_rating, :as => :admin + # attr_accessible :credit_rating, as: :admin # # def assign_attributes(values, options = {}) # sanitize_for_mass_assignment(values, options[:as]).each do |k, v| @@ -153,20 +157,20 @@ module ActiveModel # end # end # - # When using the :default role: + # When using the :default role: # # customer = Customer.new - # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default) + # customer.assign_attributes({ name: 'David', credit_rating: 'Excellent', last_login: 1.day.ago }, as: :default) # customer.name # => "David" # customer.credit_rating # => nil # - # customer.credit_rating = "Average" + # customer.credit_rating = 'Average' # customer.credit_rating # => "Average" # - # And using the :admin role: + # And using the :admin role: # # customer = Customer.new - # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin) + # customer.assign_attributes({ name: 'David', credit_rating: 'Excellent', last_login: 1.day.ago }, as: :admin) # customer.name # => "David" # customer.credit_rating # => "Excellent" # @@ -186,23 +190,131 @@ module ActiveModel self._active_authorizer = self._accessible_attributes end + # Returns an instance of ActiveModel::MassAssignmentSecurity::BlackList + # with the attributes protected by #attr_protected method. If no +role+ + # is provided, then :default is used. + # + # class Customer + # include ActiveModel::MassAssignmentSecurity + # + # attr_accessor :name, :email, :logins_count + # + # attr_protected :logins_count + # attr_protected :logins_count, :email, as: :admin + # end + # + # Customer.protected_attributes + # # => # + # + # Customer.protected_attributes(:default) + # # => # + # + # Customer.protected_attributes(:admin) + # # => # def protected_attributes(role = :default) protected_attributes_configs[role] end + # Returns an instance of ActiveModel::MassAssignmentSecurity::WhiteList + # with the attributes protected by #attr_accessible method. If no +role+ + # is provided, then :default is used. + # + # class Customer + # include ActiveModel::MassAssignmentSecurity + # + # attr_accessor :name, :credit_rating + # + # attr_accessible :name, as: [:admin, :default] + # attr_accessible :credit_rating, as: :admin + # end + # + # Customer.accessible_attributes + # # => # + # + # Customer.accessible_attributes(:default) + # # => # + # + # Customer.accessible_attributes(:admin) + # # => # def accessible_attributes(role = :default) accessible_attributes_configs[role] end + # Returns a hash with the protected attributes (by #attr_accessible or + # #attr_protected) per role. + # + # class Customer + # include ActiveModel::MassAssignmentSecurity + # + # attr_accessor :name, :credit_rating + # + # attr_accessible :name, as: [:admin, :default] + # attr_accessible :credit_rating, as: :admin + # end + # + # Customer.active_authorizers + # # => { + # # :admin=> #, + # # :default=># + # #  } def active_authorizers self._active_authorizer ||= protected_attributes_configs end alias active_authorizer active_authorizers + # Returns an empty array by default. You can still override this to define + # the default attributes protected by #attr_protected method. + # + # class Customer + # include ActiveModel::MassAssignmentSecurity + # + # def self.attributes_protected_by_default + # [:name] + # end + # end + # + # Customer.protected_attributes + # # => # def attributes_protected_by_default [] end + # Defines sanitize method. + # + # class Customer + # include ActiveModel::MassAssignmentSecurity + # + # attr_accessor :name + # + # attr_protected :name + # + # def assign_attributes(values) + # sanitize_for_mass_assignment(values).each do |k, v| + # send("#{k}=", v) + # end + # end + # end + # + # # See ActiveModel::MassAssignmentSecurity::Sanitizer::StrictSanitizer for more information. + # Customer.mass_assignment_sanitizer = :strict + # + # customer = Customer.new + # customer.assign_attributes(name: 'David') + # # => ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes for Customer: name + # + # Also, you can specify your own sanitizer object. + # + # class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer + # def process_removed_attributes(klass, attrs) + # raise StandardError + # end + # end + # + # Customer.mass_assignment_sanitizer = CustomSanitizer.new + # + # customer = Customer.new + # customer.assign_attributes(name: 'David') + # # => StandardError: StandardError def mass_assignment_sanitizer=(value) self._mass_assignment_sanitizer = if value.is_a?(Symbol) const_get(:"#{value.to_s.camelize}Sanitizer").new(self) @@ -228,11 +340,11 @@ module ActiveModel protected - def sanitize_for_mass_assignment(attributes, role = nil) + def sanitize_for_mass_assignment(attributes, role = nil) #:nodoc: _mass_assignment_sanitizer.sanitize(self.class, attributes, mass_assignment_authorizer(role)) end - def mass_assignment_authorizer(role) + def mass_assignment_authorizer(role) #:nodoc: self.class.active_authorizer[role || :default] end end -- cgit v1.2.3 From b8672914b746d3b29213a9b4b9252735f1c3ee5d Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sat, 28 Jul 2012 01:19:38 -0500 Subject: add example to ActiveModel::MissingAttributeError [ci skip] --- activemodel/lib/active_model/attribute_methods.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb index eb06250060..b1bef4b1e1 100644 --- a/activemodel/lib/active_model/attribute_methods.rb +++ b/activemodel/lib/active_model/attribute_methods.rb @@ -3,6 +3,14 @@ require 'active_support/deprecation' module ActiveModel # Raised when an attribute is not defined. + # + # class User < ActiveRecord::Base + # has_many :pets + # end + # + # user = User.first + # user.pets.select(:id).first.user_id + # # => ActiveModel::MissingAttributeError: missing attribute: user_id class MissingAttributeError < NoMethodError end # == Active Model Attribute Methods -- cgit v1.2.3 From 79b87787213fe773f87ffb39c7a286ccaa5d4a1b Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sat, 28 Jul 2012 14:24:56 -0500 Subject: add example to ActiveModel::StrictValidationFailed [ci skip] --- activemodel/lib/active_model/errors.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 4ed3462e7e..6089cb8525 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -437,6 +437,19 @@ module ActiveModel # Raised when a validation cannot be corrected by end users and are considered # exceptional. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # + # validates_presence_of :name, strict: true + # end + # + # person = Person.new + # person.name = nil + # person.valid? + # # => ActiveModel::StrictValidationFailed: Name can't be blank class StrictValidationFailed < StandardError end end -- cgit v1.2.3 From f0f7786aab7f5d494c13dd22434fd77a5c7f93c0 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 12:04:43 -0500 Subject: update ActiveModel::SecurePassword docs [ci skip] --- activemodel/lib/active_model/secure_password.rb | 56 +++++++++++++++++-------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 3eab745c89..15172d21dc 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -6,12 +6,12 @@ module ActiveModel # Adds methods to set and authenticate against a BCrypt password. # This mechanism requires you to have a password_digest attribute. # - # Validations for presence of password on create, confirmation of password (using - # a "password_confirmation" attribute) are automatically added. - # If you wish to turn off validations, pass 'validations: false' as an argument. - # You can add more validations by hand if need be. + # Validations for presence of password on create, confirmation of password + # (using a +password_confirmation+ attribute) are automatically added. If + # you wish to turn off validations, pass validations: false as an + # argument. You can add more validations by hand if need be. # - # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use has_secure_password: + # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use #has_secure_password: # # gem 'bcrypt-ruby', '~> 3.0.0' # @@ -22,35 +22,36 @@ module ActiveModel # has_secure_password # end # - # user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch") + # user = User.new(name: 'david', password: '', password_confirmation: 'nomatch') # user.save # => false, password required - # user.password = "mUc3m00RsqyRe" + # user.password = 'mUc3m00RsqyRe' # user.save # => false, confirmation doesn't match - # user.password_confirmation = "mUc3m00RsqyRe" + # user.password_confirmation = 'mUc3m00RsqyRe' # user.save # => true - # user.authenticate("notright") # => false - # user.authenticate("mUc3m00RsqyRe") # => user - # User.find_by_name("david").try(:authenticate, "notright") # => false - # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user + # user.authenticate('notright') # => false + # user.authenticate('mUc3m00RsqyRe') # => user + # User.find_by_name('david').try(:authenticate, 'notright') # => false + # User.find_by_name('david').try(:authenticate, 'mUc3m00RsqyRe') # => user def has_secure_password(options = {}) # Load bcrypt-ruby only when has_secure_password is used. - # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library. + # This is to avoid ActiveModel (and by extension the entire framework) + # being dependent on a binary library. gem 'bcrypt-ruby', '~> 3.0.0' require 'bcrypt' attr_reader :password - + if options.fetch(:validations, true) validates_confirmation_of :password validates_presence_of :password, :on => :create end - + before_create { raise "Password digest missing on new record" if password_digest.blank? } include InstanceMethodsOnActivation if respond_to?(:attributes_protected_by_default) - def self.attributes_protected_by_default + def self.attributes_protected_by_default #:nodoc: super + ['password_digest'] end end @@ -58,13 +59,32 @@ module ActiveModel end module InstanceMethodsOnActivation - # Returns self if the password is correct, otherwise false. + # Returns +self+ if the password is correct, otherwise +false+. + # + # class User < ActiveRecord::Base + # has_secure_password validations: false + # end + # + # user = User.new(name: 'david', password: 'mUc3m00RsqyRe') + # user.save + # user.authenticate('notright') # => false + #  user.authenticate('mUc3m00RsqyRe') # => user def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && self end - # Encrypts the password into the password_digest attribute, only if the + # Encrypts the password into the +password_digest+ attribute, only if the # new password is not blank. + # + # class User < ActiveRecord::Base + # has_secure_password validations: false + # end + # + # user = User.new + # user.password = nil + # user.password_digest # => nil + # user.password = 'mUc3m00RsqyRe' + # user.password_digest # => "$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/xeUVtMTYqwIvYY76EW5GUqDiP4." def password=(unencrypted_password) unless unencrypted_password.blank? @password = unencrypted_password -- cgit v1.2.3 From 78502673acdba43f712844c4a4054ff0f08ff72a Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 13:35:33 -0500 Subject: update ActiveModel::Validator docs [ci skip] --- activemodel/lib/active_model/secure_password.rb | 2 +- activemodel/lib/active_model/validator.rb | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 15172d21dc..6cba29feef 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -11,7 +11,7 @@ module ActiveModel # you wish to turn off validations, pass validations: false as an # argument. You can add more validations by hand if need be. # - # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use #has_secure_password: + # You need to add bcrypt-ruby (~> 3.0.0) to Gemfile to use #has_secure_password: # # gem 'bcrypt-ruby', '~> 3.0.0' # diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index d5d0798704..17c1539fc4 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -2,7 +2,7 @@ require "active_support/core_ext/module/anonymous" require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/inclusion' -module ActiveModel #:nodoc: +module ActiveModel # == Active Model Validator # @@ -28,7 +28,7 @@ module ActiveModel #:nodoc: # end # # Any class that inherits from ActiveModel::Validator must implement a method - # called validate which accepts a record. + # called +validate+ which accepts a +record+. # # class Person # include ActiveModel::Validations @@ -42,8 +42,8 @@ module ActiveModel #:nodoc: # end # end # - # To cause a validation error, you must add to the record's errors directly - # from within the validators message + # To cause a validation error, you must add to the +record+'s errors directly + # from within the validators message. # # class MyValidator < ActiveModel::Validator # def validate(record) @@ -63,7 +63,7 @@ module ActiveModel #:nodoc: # end # # The easiest way to add custom validators for validating individual attributes - # is with the convenient ActiveModel::EachValidator. For example: + # is with the convenient ActiveModel::EachValidator. # # class TitleValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) @@ -72,7 +72,7 @@ module ActiveModel #:nodoc: # end # # This can now be used in combination with the +validates+ method - # (see ActiveModel::Validations::ClassMethods.validates for more on this) + # (see ActiveModel::Validations::ClassMethods.validates for more on this). # # class Person # include ActiveModel::Validations @@ -83,8 +83,7 @@ module ActiveModel #:nodoc: # # Validator may also define a +setup+ instance method which will get called # with the class that using that validator as its argument. This can be - # useful when there are prerequisites such as an +attr_accessor+ being present - # for example: + # useful when there are prerequisites such as an +attr_accessor+ being present. # # class MyValidator < ActiveModel::Validator # def setup(klass) @@ -94,7 +93,6 @@ module ActiveModel #:nodoc: # # This setup method is only called when used with validation macros or the # class level validates_with method. - # class Validator attr_reader :options @@ -102,7 +100,6 @@ module ActiveModel #:nodoc: # # PresenceValidator.kind # => :presence # UniquenessValidator.kind # => :uniqueness - # def self.kind @kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous? end @@ -113,6 +110,9 @@ module ActiveModel #:nodoc: end # Return the kind for this validator. + # + # PresenceValidator.new.kind # => :presence + # UniquenessValidator.new.kind # => :uniqueness  def kind self.class.kind end -- cgit v1.2.3 From 01e61eed6a89a756422a17984c20666de51f8dae Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 19:52:25 -0500 Subject: =?UTF-8?q?update=20ActiveModel::Validations=20docs=C2=A0[ci=20ski?= =?UTF-8?q?p]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- activemodel/lib/active_model/validations.rb | 161 ++++++++++++++++++++++------ activemodel/lib/active_model/validator.rb | 2 +- 2 files changed, 127 insertions(+), 36 deletions(-) diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 55ea6be796..0634c47602 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -33,11 +33,11 @@ module ActiveModel # person.first_name = 'zoolander' # person.valid? # => false # person.invalid? # => true - # person.errors # => #["starts with z."]}> + # person.errors.messages # => {:first_name=>["starts with z."]} # - # Note that ActiveModel::Validations automatically adds an +errors+ method - # to your instances initialized with a new ActiveModel::Errors object, so - # there is no need for you to do this manually. + # Note that ActiveModel::Validations automatically adds an +errors+ + # method to your instances initialized with a new ActiveModel::Errors + # object, so there is no need for you to do this manually. module Validations extend ActiveSupport::Concern @@ -63,24 +63,25 @@ module ActiveModel # # attr_accessor :first_name, :last_name # - # validates_each :first_name, :last_name, :allow_blank => true do |record, attr, value| + # validates_each :first_name, :last_name, allow_blank: true do |record, attr, value| # record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z # end # end # # Options: # * :on - Specifies the context where this validation is active - # (e.g. :on => :create or :on => :custom_validation_context) + # (e.g. on: :create or on: :custom_validation_context) # * :allow_nil - Skip validation if attribute is +nil+. # * :allow_blank - Skip validation if attribute is blank. # * :if - Specifies a method, proc or string to call to determine - # if the validation should occur (e.g. :if => :allow_validation, - # or :if => Proc.new { |user| user.signup_step > 2 }). The method, - # proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or - # :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # if the validation should occur (e.g. if: :allow_validation, + # or if: Proc.new { |user| user.signup_step > 2 }). The method, + # proc or string should return or evaluate to a +true+ or +false+ value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should not occur (e.g. unless: :skip_validation, + # or unless: Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a +true+ or +false+ + # value. def validates_each(*attr_names, &block) validates_with BlockValidator, _merge_attributes(attr_names), &block end @@ -97,7 +98,7 @@ module ActiveModel # validate :must_be_friends # # def must_be_friends - # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # @@ -111,7 +112,7 @@ module ActiveModel # end # # def must_be_friends - # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # @@ -121,23 +122,24 @@ module ActiveModel # include ActiveModel::Validations # # validate do - # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee) # end # end # # Options: # * :on - Specifies the context where this validation is active - # (e.g. :on => :create or :on => :custom_validation_context) + # (e.g. on: :create or on: :custom_validation_context) # * :allow_nil - Skip validation if attribute is +nil+. # * :allow_blank - Skip validation if attribute is blank. # * :if - Specifies a method, proc or string to call to determine - # if the validation should occur (e.g. :if => :allow_validation, - # or :if => Proc.new { |user| user.signup_step > 2 }). The method, - # proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or - # :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # if the validation should occur (e.g. if: :allow_validation, + # or if: Proc.new { |user| user.signup_step > 2 }). The method, + # proc or string should return or evaluate to a +true+ or +false+ value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should not occur (e.g. unless: :skip_validation, + # or unless: Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a +true+ or +false+ + # value. def validate(*args, &block) options = args.extract_options! if options.key?(:on) @@ -171,39 +173,101 @@ module ActiveModel end # List all validators that are being used to validate a specific attribute. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name , :age + # + # validates_presence_of :name + # validates_inclusion_of :age, in: 0..99 + # end + # + # Person.validators_on(:name) + # # => [ + # # #, + # # #0..99}> + # # ] def validators_on(*attributes) attributes.map do |attribute| _validators[attribute.to_sym] end.flatten end - # Check if method is an attribute method or not. + # Returns +true+ if +attribute+ is an attribute method, +false+ otherwise. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # end + # + # User.attribute_method?(:name) # => true + # User.attribute_method?(:age) # => false def attribute_method?(attribute) method_defined?(attribute) end # Copy validators on inheritance. - def inherited(base) + def inherited(base) #:nodoc: dup = _validators.dup base._validators = dup.each { |k, v| dup[k] = v.dup } super end end - # Clean the +Errors+ object if instance is duped - def initialize_dup(other) # :nodoc: + # Clean the +Errors+ object if instance is duped. + def initialize_dup(other) #:nodoc: @errors = nil super end - # Returns the +Errors+ object that holds all information about attribute error messages. + # Returns the +Errors+ object that holds all information about attribute + # error messages. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # validates_presence_of :name + # end + # + # person = Person.new + # person.valid? # => false + # person.errors # => #["can't be blank"]}> def errors @errors ||= Errors.new(self) end - # Runs all the specified validations and returns true if no errors were added - # otherwise false. Context can optionally be supplied to define which callbacks - # to test against (the context is defined on the validations using :on). + # Runs all the specified validations and returns +true+ if no errors were + # added otherwise +false+. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # validates_presence_of :name + # end + # + # person = Person.new + # person.name = '' + # person.valid? # => false + # person.name = 'david' + # person.valid? # => true + # + # Context can optionally be supplied to define which callbacks to test + # against (the context is defined on the validations using :on). + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # validates_presence_of :name, on: :new + # end + # + # person = Person.new + # person.valid? # => true + # person.valid?(:new) # => false def valid?(context = nil) current_context, self.validation_context = validation_context, context errors.clear @@ -212,8 +276,35 @@ module ActiveModel self.validation_context = current_context end - # Performs the opposite of valid?. Returns true if errors were added, - # false otherwise. + # Performs the opposite of valid?. Returns +true+ if errors were + # added, +false+ otherwise. + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # validates_presence_of :name + # end + # + # person = Person.new + # person.name = '' + # person.invalid? # => true + # person.name = 'david' + # person.invalid? # => false + # + # Context can optionally be supplied to define which callbacks to test + # against (the context is defined on the validations using :on). + # + # class Person + # include ActiveModel::Validations + # + # attr_accessor :name + # validates_presence_of :name, on: :new + # end + # + # person = Person.new + # person.invalid? # => false + # person.invalid?(:new) # => true def invalid?(context = nil) !valid?(context) end @@ -238,7 +329,7 @@ module ActiveModel protected - def run_validations! + def run_validations! #:nodoc: run_callbacks :validate errors.empty? end diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 17c1539fc4..3da32b9201 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -96,7 +96,7 @@ module ActiveModel class Validator attr_reader :options - # Returns the kind of the validator. Examples: + # Returns the kind of the validator. # # PresenceValidator.kind # => :presence # UniquenessValidator.kind # => :uniqueness -- cgit v1.2.3 From 0557273f38fcbdaa661715dbb2c2d8ffaf264e36 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 19:57:48 -0500 Subject: update ActiveModel::Valdations#validates_with docs [ci skip] --- activemodel/lib/active_model/validations/with.rb | 34 +++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 3c516f8b22..869591cd9e 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -34,7 +34,7 @@ module ActiveModel # class MyValidator < ActiveModel::Validator # def validate(record) # if some_complex_logic - # record.errors.add :base, "This record is invalid" + # record.errors.add :base, 'This record is invalid' # end # end # @@ -48,30 +48,32 @@ module ActiveModel # # class Person # include ActiveModel::Validations - # validates_with MyValidator, MyOtherValidator, :on => :create + # validates_with MyValidator, MyOtherValidator, on: :create # end # # Configuration options: # * :on - Specifies when this validation is active - # (:create or :update + # (:create or :update. # * :if - Specifies a method, proc or string to call to determine - # if the validation should occur (e.g. :if => :allow_validation, - # or :if => Proc.new { |user| user.signup_step > 2 }). - # The method, proc or string should return or evaluate to a true or false value. + # if the validation should occur (e.g. if: :allow_validation, + # or if: Proc.new { |user| user.signup_step > 2 }). + # The method, proc or string should return or evaluate to a +true+ or + # +false+ value. # * :unless - Specifies a method, proc or string to call to # determine if the validation should not occur - # (e.g. :unless => :skip_validation, or - # :unless => Proc.new { |user| user.signup_step <= 2 }). - # The method, proc or string should return or evaluate to a true or false value. + # (e.g. unless: :skip_validation, or + # unless: Proc.new { |user| user.signup_step <= 2 }). + # The method, proc or string should return or evaluate to a +true+ or + # +false+ value. # * :strict - Specifies whether validation should be strict. # See ActiveModel::Validation#validates! for more information. # # If you pass any additional configuration options, they will be passed - # to the class and available as options: + # to the class and available as +options+: # # class Person # include ActiveModel::Validations - # validates_with MyValidator, :my_custom_key => "my custom value" + # validates_with MyValidator, my_custom_key: 'my custom value' # end # # class MyValidator < ActiveModel::Validator @@ -119,17 +121,17 @@ module ActiveModel # class Person # include ActiveModel::Validations # - # validate :instance_validations, :on => :create + # validate :instance_validations, on: :create # # def instance_validations # validates_with MyValidator, MyOtherValidator # end # end # - # Standard configuration options (:on, :if and :unless), which are - # available on the class version of +validates_with+, should instead be - # placed on the +validates+ method as these are applied and tested - # in the callback. + # Standard configuration options (:on, :if and + # :unless), which are available on the class version of + # +validates_with+, should instead be placed on the +validates+ method + # as these are applied and tested in the callback. # # If you pass any additional configuration options, they will be passed # to the class and available as +options+, please refer to the -- cgit v1.2.3 From 097bfc8296eea8326ee2c62c1dd953b68f539ea5 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 20:08:42 -0500 Subject: update #validates and #validates! documentation [ci skip] --- .../lib/active_model/validations/validates.rb | 74 +++++++++++++--------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index ecda9dffcf..5892ad29d1 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -11,18 +11,18 @@ module ActiveModel # # Examples of using the default rails validators: # - # validates :terms, :acceptance => true - # validates :password, :confirmation => true - # validates :username, :exclusion => { :in => %w(admin superuser) } - # validates :email, :format => { :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create } - # validates :age, :inclusion => { :in => 0..9 } - # validates :first_name, :length => { :maximum => 30 } - # validates :age, :numericality => true - # validates :username, :presence => true - # validates :username, :uniqueness => true + # validates :terms, acceptance: true + # validates :password, confirmation: true + # validates :username, exclusion: { in: %w(admin superuser) } + # validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, on: :create } + # validates :age, inclusion: { in: 0..9 } + # validates :first_name, length: { maximum: 30 } + # validates :age, numericality: true + # validates :username, presence: true + # validates :username, uniqueness: true # # The power of the +validates+ method comes when using custom validators - # and default validators in one call for a given attribute e.g. + # and default validators in one call for a given attribute. # # class EmailValidator < ActiveModel::EachValidator # def validate_each(record, attribute, value) @@ -35,12 +35,12 @@ module ActiveModel # include ActiveModel::Validations # attr_accessor :name, :email # - # validates :name, :presence => true, :uniqueness => true, :length => { :maximum => 100 } - # validates :email, :presence => true, :email => true + # validates :name, presence: true, uniqueness: true, length: { maximum: 100 } + # validates :email, presence: true, email: true # end # # Validator classes may also exist within the class being validated - # allowing custom modules of validators to be included as needed e.g. + # allowing custom modules of validators to be included as needed. # # class Film # include ActiveModel::Validations @@ -51,25 +51,27 @@ module ActiveModel # end # end # - # validates :name, :title => true + # validates :name, title: true # end # - # Additionally validator classes may be in another namespace and still used within any class. + # Additionally validator classes may be in another namespace and still + # used within any class. # # validates :name, :'film/title' => true # - # The validators hash can also handle regular expressions, ranges, - # arrays and strings in shortcut form, e.g. + # The validators hash can also handle regular expressions, ranges, arrays + # and strings in shortcut form. # - # validates :email, :format => /@/ - # validates :gender, :inclusion => %w(male female) - # validates :password, :length => 6..20 + # validates :email, format: /@/ + # validates :gender, inclusion: %w(male female) + # validates :password, length: 6..20 # # When using shortcut form, ranges and arrays are passed to your - # validator's initializer as +options[:in]+ while other types including - # regular expressions and strings are passed as +options[:with]+ + # validator's initializer as options[:in] while other types + # including regular expressions and strings are passed as options[:with]. # # There is also a list of options that could be used along with validators: + # # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. @@ -87,14 +89,12 @@ module ActiveModel # # Example: # - # validates :password, :presence => true, :confirmation => true, :if => :password_required? - # - # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ and +:strict+ - # can be given to one specific validator, as a hash: - # - # validates :password, :presence => { :if => :password_required? }, :confirmation => true + # validates :password, presence: true, confirmation: true, if: :password_required? # + # Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ + # and +:strict+ can be given to one specific validator, as a hash: # + # validates :password, presence: { if: :password_required? }, confirmation: true def validates(*attributes) defaults = attributes.extract_options!.dup validations = defaults.slice!(*_validates_default_keys) @@ -122,8 +122,20 @@ module ActiveModel # users and are considered exceptional. So each validator defined with bang # or :strict option set to true will always raise # ActiveModel::StrictValidationFailed instead of adding error - # when validation fails. - # See validates for more information about the validation itself. + # when validation fails. See validates for more information about + # the validation itself. + # + # class Person + #  include ActiveModel::Validations + # + # attr_accessor :name + # validates! :name, presence: true + # end + # + # person = Person.new + #  person.name = '' + #  person.valid? + # # => ActiveModel::StrictValidationFailed: Name can't be blank def validates!(*attributes) options = attributes.extract_options! options[:strict] = true @@ -134,7 +146,7 @@ module ActiveModel # When creating custom validators, it might be useful to be able to specify # additional default keys. This can be done by overwriting this method. - def _validates_default_keys + def _validates_default_keys #:nodoc: [:if, :unless, :on, :allow_blank, :allow_nil , :strict] end -- cgit v1.2.3 From cb6c3e28afe2a2dca04cbb398823c664ab857800 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 22:40:37 -0500 Subject: update ActiveModel::Validations::Callbacks documentation [ci skip] --- .../lib/active_model/validations/callbacks.rb | 87 +++++++++++++++++----- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index dbafd0bd1a..03a44a0e29 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -2,24 +2,24 @@ require 'active_support/callbacks' module ActiveModel module Validations + # == Active Model Validation callbacks + # + # Provides an interface for any class to have +before_validation+ and + # +after_validation+ callbacks. + # + # First, include ActiveModel::Validations::Callbacks from the class you are + # creating: + # + # class MyModel + # include ActiveModel::Validations::Callbacks + # + # before_validation :do_stuff_before_validation + # after_validation :do_stuff_after_validation + # end + # + # Like other before_* callbacks if +before_validation+ returns + # +false+ then valid? will not be called. module Callbacks - # == Active Model Validation callbacks - # - # Provides an interface for any class to have before_validation and - # after_validation callbacks. - # - # First, include ActiveModel::Validations::Callbacks from the class you are - # creating: - # - # class MyModel - # include ActiveModel::Validations::Callbacks - # - # before_validation :do_stuff_before_validation - # after_validation :do_stuff_after_validation - # end - # - # Like other before_* callbacks if before_validation returns false - # then valid? will not be called. extend ActiveSupport::Concern included do @@ -28,6 +28,30 @@ module ActiveModel end module ClassMethods + # Defines a callback that will get called right before validation + # happens. + # + # class Person + # include ActiveModel::Validations + # include ActiveModel::Validations::Callbacks + # + # attr_accessor :name + # + # validates_length_of :name, maximum: 6 + # + # before_validation :remove_whitespaces + # + # private + # + # def remove_whitespaces + # name.strip! + # end + # end + # + # person = Person.new + # person.name = ' bob ' + # person.valid? # => true + # person.name # => "bob" def before_validation(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] @@ -37,6 +61,33 @@ module ActiveModel set_callback(:validation, :before, *args, &block) end + # Defines a callback that will get called right after validation + # happens. + # + # class Person + # include ActiveModel::Validations + # include ActiveModel::Validations::Callbacks + # + # attr_accessor :name, :status + # + # validates_presence_of :name + # + # after_validation :set_status + # + # private + # + # def set_status + # self.status = (errors.empty?) ? true : false + # end + # end + # + # person = Person.new + # person.name = '' + # person.valid? # => false + # person.status # => false + #  person.name = 'bob' + # person.valid? # => true + # person.status # => true def after_validation(*args, &block) options = args.extract_options! options[:prepend] = true @@ -49,7 +100,7 @@ module ActiveModel protected # Overwrite run validations to include callbacks. - def run_validations! + def run_validations! #:nodoc: run_callbacks(:validation) { super } end end -- cgit v1.2.3 From c57b8d236bbca25fa655a7ed48ae60dd46c0f257 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 22:56:04 -0500 Subject: fix class reference in AM::MassAssignmentSecurity documentation [ci skip] --- activemodel/lib/active_model/mass_assignment_security.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index 540b90c4cc..19359896d0 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -4,7 +4,7 @@ require 'active_model/mass_assignment_security/permission_set' require 'active_model/mass_assignment_security/sanitizer' module ActiveModel - # = Active Model Mass-Assignment Security + # == Active Model Mass-Assignment Security # # Mass assignment security provides an interface for protecting attributes # from end-user assignment. For more complex permissions, mass assignment @@ -35,7 +35,7 @@ module ActiveModel # # end # - # = Configuration options + # === Configuration options # # * mass_assignment_sanitizer - Defines sanitize method. Possible # values are: @@ -295,7 +295,7 @@ module ActiveModel # end # end # - # # See ActiveModel::MassAssignmentSecurity::Sanitizer::StrictSanitizer for more information. + # # See ActiveModel::MassAssignmentSecurity::StrictSanitizer for more information. # Customer.mass_assignment_sanitizer = :strict # # customer = Customer.new -- cgit v1.2.3 From 4d1794713e68263ef2db49cf633a84b0c07b69f7 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 23:09:24 -0500 Subject: add :nodoc: directives to ActiveModel Sanitizers [ci skip] --- .../lib/active_model/mass_assignment_security/sanitizer.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb index 44ce5a489d..dafb7cdff3 100644 --- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb +++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb @@ -1,6 +1,6 @@ module ActiveModel module MassAssignmentSecurity - class Sanitizer + class Sanitizer #:nodoc: # Returns all attributes not denied by the authorizer. def sanitize(klass, attributes, authorizer) rejected = [] @@ -18,7 +18,7 @@ module ActiveModel end end - class LoggerSanitizer < Sanitizer + class LoggerSanitizer < Sanitizer #:nodoc: def initialize(target) @target = target super() @@ -50,7 +50,7 @@ module ActiveModel end end - class StrictSanitizer < Sanitizer + class StrictSanitizer < Sanitizer #:nodoc: def initialize(target = nil) super() end @@ -65,7 +65,7 @@ module ActiveModel end end - class Error < StandardError + class Error < StandardError #:nodoc: def initialize(klass, attrs) super("Can't mass-assign protected attributes for #{klass.name}: #{attrs.join(', ')}") end -- cgit v1.2.3 From 1cd40decd30d606b8e6a95b8e72e185fe8a5a8f0 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 23:20:27 -0500 Subject: update AR::Validations::UniquenessValidator documentation [ci skip] --- .../lib/active_record/validations/uniqueness.rb | 76 +++++++++++++--------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 5a24135f8e..c117872ac8 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -2,7 +2,7 @@ require 'active_support/core_ext/array/prepend_and_append' module ActiveRecord module Validations - class UniquenessValidator < ActiveModel::EachValidator + class UniquenessValidator < ActiveModel::EachValidator #:nodoc: def initialize(options) super(options.reverse_merge(:case_sensitive => true)) end @@ -87,54 +87,67 @@ module ActiveRecord end module ClassMethods - # Validates whether the value of the specified attributes are unique across the system. - # Useful for making sure that only one user + # Validates whether the value of the specified attributes are unique + # across the system. Useful for making sure that only one user # can be named "davidhh". # # class Person < ActiveRecord::Base # validates_uniqueness_of :user_name # end # - # It can also validate whether the value of the specified attributes are unique based on a scope parameter: + # It can also validate whether the value of the specified attributes are + # unique based on a :scope parameter: # # class Person < ActiveRecord::Base - # validates_uniqueness_of :user_name, :scope => :account_id + # validates_uniqueness_of :user_name, scope: :account_id # end # - # Or even multiple scope parameters. For example, making sure that a teacher can only be on the schedule once - # per semester for a particular class. + # Or even multiple scope parameters. For example, making sure that a + # teacher can only be on the schedule once per semester for a particular + # class. # # class TeacherSchedule < ActiveRecord::Base - # validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id] + # validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id] # end # - # It is also possible to limit the uniqueness constraint to a set of records matching certain conditions. - # In this example archived articles are not being taken into consideration when validating uniqueness + # It is also possible to limit the uniqueness constraint to a set of + # records matching certain conditions. In this example archived articles + # are not being taken into consideration when validating uniqueness # of the title attribute: # # class Article < ActiveRecord::Base - # validates_uniqueness_of :title, :conditions => where('status != ?', 'archived') + # validates_uniqueness_of :title, conditions: where('status != ?', 'archived') # end # - # When the record is created, a check is performed to make sure that no record exists in the database - # with the given value for the specified attribute (that maps to a column). When the record is updated, + # When the record is created, a check is performed to make sure that no + # record exists in the database with the given value for the specified + # attribute (that maps to a column). When the record is updated, # the same check is made but disregarding the record itself. # # Configuration options: - # * :message - Specifies a custom error message (default is: "has already been taken"). - # * :scope - One or more columns by which to limit the scope of the uniqueness constraint. - # * :conditions - Specify the conditions to be included as a WHERE SQL fragment to limit - # the uniqueness constraint lookup. (e.g. :conditions => where('status = ?', 'active')) - # * :case_sensitive - Looks for an exact match. Ignored by non-text columns (+true+ by default). - # * :allow_nil - If set to true, skips this validation if the attribute is +nil+ (default is +false+). - # * :allow_blank - If set to true, skips this validation if the attribute is blank (default is +false+). - # * :if - Specifies a method, proc or string to call to determine if the validation should - # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). - # The method, proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or - # :unless => Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should - # return or evaluate to a true or false value. + # + # * :message - Specifies a custom error message (default is: + # "has already been taken"). + # * :scope - One or more columns by which to limit the scope of + # the uniqueness constraint. + # * :conditions - Specify the conditions to be included as a + # WHERE SQL fragment to limit the uniqueness constraint lookup + # (e.g. conditions: where('status = ?', 'active')). + # * :case_sensitive - Looks for an exact match. Ignored by + # non-text columns (+true+ by default). + # * :allow_nil - If set to +true+, skips this validation if the + # attribute is +nil+ (default is +false+). + # * :allow_blank - If set to +true+, skips this validation if the + # attribute is blank (default is +false+). + # * :if - Specifies a method, proc or string to call to determine + # if the validation should occur (e.g. if: :allow_validation, + # or if: Proc.new { |user| user.signup_step > 2 }). The method, + # proc or string should return or evaluate to a +true+ or +false+ value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should ot occur (e.g. unless: :skip_validation, + # or unless: Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a +true+ or +false+ + # value. # # === Concurrency and integrity # @@ -190,15 +203,16 @@ module ActiveRecord # # The bundled ActiveRecord::ConnectionAdapters distinguish unique index # constraint errors from other types of database errors by throwing an - # ActiveRecord::RecordNotUnique exception. - # For other adapters you will have to parse the (database-specific) exception - # message to detect such a case. + # ActiveRecord::RecordNotUnique exception. For other adapters you will + # have to parse the (database-specific) exception message to detect such + # a case. + # # The following bundled adapters throw the ActiveRecord::RecordNotUnique exception: + # # * ActiveRecord::ConnectionAdapters::MysqlAdapter # * ActiveRecord::ConnectionAdapters::Mysql2Adapter # * ActiveRecord::ConnectionAdapters::SQLite3Adapter # * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter - # def validates_uniqueness_of(*attr_names) validates_with UniquenessValidator, _merge_attributes(attr_names) end -- cgit v1.2.3 From ea881ef9969a2dafb71ec7a0e193acb592bf2cce Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Sun, 29 Jul 2012 23:23:45 -0500 Subject: update AR::Validations::AssociatedValidator documentation [ci skip] --- .../lib/active_record/validations/associated.rb | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/activerecord/lib/active_record/validations/associated.rb b/activerecord/lib/active_record/validations/associated.rb index afce149da9..1fa6629980 100644 --- a/activerecord/lib/active_record/validations/associated.rb +++ b/activerecord/lib/active_record/validations/associated.rb @@ -1,6 +1,6 @@ module ActiveRecord module Validations - class AssociatedValidator < ActiveModel::EachValidator + class AssociatedValidator < ActiveModel::EachValidator #:nodoc: def validate_each(record, attribute, value) if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?(record.validation_context) }.any? record.errors.add(attribute, :invalid, options.merge(:value => value)) @@ -9,7 +9,8 @@ module ActiveRecord end module ClassMethods - # Validates whether the associated object or objects are all valid themselves. Works with any kind of association. + # Validates whether the associated object or objects are all valid + # themselves. Works with any kind of association. # # class Book < ActiveRecord::Base # has_many :pages @@ -18,23 +19,28 @@ module ActiveRecord # validates_associated :pages, :library # end # - # WARNING: This validation must not be used on both ends of an association. Doing so will lead to a circular dependency and cause infinite recursion. + # WARNING: This validation must not be used on both ends of an association. + # Doing so will lead to a circular dependency and cause infinite recursion. # - # NOTE: This validation will not fail if the association hasn't been assigned. If you want to - # ensure that the association is both present and guaranteed to be valid, you also need to - # use +validates_presence_of+. + # NOTE: This validation will not fail if the association hasn't been + # assigned. If you want to ensure that the association is both present and + # guaranteed to be valid, you also need to use +validates_presence_of+. # # Configuration options: - # * :message - A custom error message (default is: "is invalid") + # + # * :message - A custom error message (default is: "is invalid"). # * :on - Specifies when this validation is active. Runs in all # validation contexts by default (+nil+), other options are :create # and :update. - # * :if - Specifies a method, proc or string to call to determine if the validation should - # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The - # method, proc or string should return or evaluate to a true or false value. - # * :unless - Specifies a method, proc or string to call to determine if the validation should - # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The - # method, proc or string should return or evaluate to a true or false value. + # * :if - Specifies a method, proc or string to call to determine + # if the validation should occur (e.g. if: :allow_validation, + # or if: Proc.new { |user| user.signup_step > 2 }). The method, + # proc or string should return or evaluate to a +true+ or +false+ value. + # * :unless - Specifies a method, proc or string to call to + # determine if the validation should not occur (e.g. unless: :skip_validation, + # or unless: => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a +true+ or +false+ + # value. def validates_associated(*attr_names) validates_with AssociatedValidator, _merge_attributes(attr_names) end -- cgit v1.2.3 From 81bf120c340a2b9db13e96cad7f08bc2733a1ffe Mon Sep 17 00:00:00 2001 From: Vladimir Strakhov Date: Mon, 30 Jul 2012 11:06:02 +0400 Subject: add mysql authentification command to chapter 2.Running the Test Suite --- guides/source/contributing_to_ruby_on_rails.textile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guides/source/contributing_to_ruby_on_rails.textile b/guides/source/contributing_to_ruby_on_rails.textile index a8a097d156..35ec988c5e 100644 --- a/guides/source/contributing_to_ruby_on_rails.textile +++ b/guides/source/contributing_to_ruby_on_rails.textile @@ -184,6 +184,10 @@ We need first to delete +.bundle/config+ because Bundler remembers in that 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: + +mysql -u root mysql -p + + mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost'; -- cgit v1.2.3 From 1ca957c5bb6d33a84a0a69681e66de79c702930d Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 10:55:06 -0500 Subject: fix #after_validation example [ci skip] --- activemodel/lib/active_model/validations/callbacks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 03a44a0e29..bf3fe7ff04 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -77,7 +77,7 @@ module ActiveModel # private # # def set_status - # self.status = (errors.empty?) ? true : false + # self.status = errors.empty? # end # end # -- cgit v1.2.3 From ba94c6b76d443a5bea55b144461910e690016452 Mon Sep 17 00:00:00 2001 From: Novikov Andrey Date: Tue, 31 Jul 2012 09:15:06 +1000 Subject: Add 'Writing Rake Tasks' subsection to Command Line Guide --- guides/source/command_line.textile | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/guides/source/command_line.textile b/guides/source/command_line.textile index 19e42cea93..1ed0c48933 100644 --- a/guides/source/command_line.textile +++ b/guides/source/command_line.textile @@ -477,6 +477,53 @@ h4. Miscellaneous * +rake secret+ will give you a pseudo-random key to use for your session secret. * rake time:zones:all lists all the timezones Rails knows about. +h4. Writing Rake Tasks + +If you have (or want to write) any automation scripts outside your app (data import, checks, etc), you can make them as rake tasks. It's easy. + +INFO: "Complete guide about how to write tasks":http://rake.rubyforge.org/files/doc/rakefile_rdoc.html is available in the official documentation. + +Tasks should be placed in Rails.root/lib/tasks and should have a +.rake+ extension. + +Each task should be defined in next format (dependencies are optional): + + +desc "I am short, but comprehensive description for my cool task" +task :task_name => [:prerequisite_task, :another_task_we_depend_on] do + # All your magick here + # Any valid Ruby code is allowed +end + + +If you need to pass parameters, you can use next format (both arguments and dependencies are optional): + + +task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args| + # You can use args from here +end + + +You can group tasks by placing them in namespaces: + + +namespace :do + desc "This task does nothing" + task :nothing do + # Seriously, nothing + end +end + + +You can see your tasks to be listed by rake -T command. And, according to the examples above, you can invoke them as follows: + + +rake task_name +rake "task_name[value 1]" # entire argument string should be quoted +rake do:nothing + + +NOTE: If your need to interact with your application models, perform database queries and so on, your task should depend on the +environment+ task, which will load your application code. + h3. The Rails Advanced Command Line More advanced use of the command line is focused around finding useful (even surprising at times) options in the utilities, and fitting those to your needs and specific work flow. Listed here are some tricks up Rails' sleeve. -- cgit v1.2.3 From 4ff5a5df4d08fad1ed26164a057be152e40bf8d9 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 21:19:35 -0500 Subject: add documentation to ActiveModel #from_json method [ci skip] --- activemodel/lib/active_model/serializers/json.rb | 36 ++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb index e4c7553cb8..ee888d3ee1 100644 --- a/activemodel/lib/active_model/serializers/json.rb +++ b/activemodel/lib/active_model/serializers/json.rb @@ -19,8 +19,8 @@ module ActiveModel # passed through +options+. # # The option include_root_in_json controls the top-level behavior - # of +as_json+. If true +as_json+ will emit a single root node named after - # the object's type. The default value for include_root_in_json + # of +as_json+. If +true+, +as_json+ will emit a single root node named + # after the object's type. The default value for include_root_in_json # option is +false+. # # user = User.find(1) @@ -101,6 +101,38 @@ module ActiveModel end end + # Sets the model +attributes+ from a JSON string. Returns +self+. + # + # class Person + # include ActiveModel::Serializers::JSON + # + # attr_accessor :name, :age, :awesome + # + # def attributes=(hash) + # hash.each do |key, value| + # instance_variable_set("@#{key}", value) + # end + # end + # + # def attributes + # instance_values + # end + # end + # + # person = Person.new + # person.from_json("{\"name\":\"bob\",\"age\":22,\"awesome\":true}") + # person.name # => "bob" + # person.age # => 22 + # person.awesome # => true + # + # The default value for +include_root+ is +false+. You can change it to + # +true+ if the given JSON string includes a single root node. + # + # person = Person.new + # person.from_json("{\"person\":{\"name\":\"bob\",\"age\":22,\"awesome\":true}}", true) + # person.name # => "bob" + # person.age # => 22 + # person.awesome # => true def from_json(json, include_root=include_root_in_json) hash = ActiveSupport::JSON.decode(json) hash = hash.values.first if include_root -- cgit v1.2.3 From d67b289796bd121bfe8d2b5d20d157a011116dfe Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 21:32:44 -0500 Subject: update ActiveModel::Serializers documentation [ci skip] --- activemodel/lib/active_model/serializers/json.rb | 18 ++++++------ activemodel/lib/active_model/serializers/xml.rb | 36 ++++++++++++++++++++---- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb index ee888d3ee1..1894e21774 100644 --- a/activemodel/lib/active_model/serializers/json.rb +++ b/activemodel/lib/active_model/serializers/json.rb @@ -119,20 +119,22 @@ module ActiveModel # end # end # + # json = { name: 'bob', age: 22, awesome:true }.to_json # person = Person.new - # person.from_json("{\"name\":\"bob\",\"age\":22,\"awesome\":true}") - # person.name # => "bob" - # person.age # => 22 - # person.awesome # => true + # person.from_json(json) # => # + # person.name # => "bob" + # person.age # => 22 + # person.awesome # => true # # The default value for +include_root+ is +false+. You can change it to # +true+ if the given JSON string includes a single root node. # + # json = { person: { name: 'bob', age: 22, awesome:true } }.to_json # person = Person.new - # person.from_json("{\"person\":{\"name\":\"bob\",\"age\":22,\"awesome\":true}}", true) - # person.name # => "bob" - # person.age # => 22 - # person.awesome # => true + # person.from_json(json) # => # + # person.name # => "bob" + # person.age # => 22 + # person.awesome # => true def from_json(json, include_root=include_root_in_json) hash = ActiveSupport::JSON.decode(json) hash = hash.values.first if include_root diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 2b3e9ce134..96ae47cec1 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -110,7 +110,7 @@ module ActiveModel end end - # TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well. + # TODO: This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well. def add_associations(association, records, opts) merged_options = opts.merge(options.slice(:builder, :indent)) merged_options[:skip_instruct] = true @@ -161,8 +161,8 @@ module ActiveModel # Returns XML representing the model. Configuration can be # passed through +options+. # - # Without any +options+, the returned XML string will include all the model's - # attributes. For example: + # Without any +options+, the returned XML string will include all the + # model's attributes. # # user = User.find(1) # user.to_xml @@ -175,18 +175,42 @@ module ActiveModel # 2011-01-30T22:29:23Z # # - # The :only and :except options can be used to limit the attributes - # included, and work similar to the +attributes+ method. + # The :only and :except options can be used to limit the + # attributes included, and work similar to the +attributes+ method. # # To include the result of some method calls on the model use :methods. # # To include associations use :include. # - # For further documentation see activerecord/lib/active_record/serializers/xml_serializer.xml. + # For further documentation, see activerecord/lib/active_record/serializers/xml_serializer.xml. def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end + # Sets the model +attributes+ from a JSON string. Returns +self+. + # + # class Person + # include ActiveModel::Serializers::Xml + # + # attr_accessor :name, :age, :awesome + # + # def attributes=(hash) + # hash.each do |key, value| + # instance_variable_set("@#{key}", value) + # end + # end + # + # def attributes + # instance_values + # end + # end + # + # xml = { name: 'bob', age: 22, awesome:true }.to_xml + # person = Person.new + # person.from_xml(xml) # => # + # person.name # => "bob" + # person.age # => 22 + # person.awesome # => true def from_xml(xml) self.attributes = Hash.from_xml(xml).values.first self -- cgit v1.2.3 From cb15fe55dab3287562f0f90d7a8ca1d1c9f5c162 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 23:15:27 -0500 Subject: update ActiveModel::Observing documentation [ci skip] --- activemodel/lib/active_model/observing.rb | 150 +++++++++++++++++++++++++----- 1 file changed, 125 insertions(+), 25 deletions(-) diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index ca206ee9aa..1114ac962a 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -9,6 +9,7 @@ require 'active_support/core_ext/object/try' require 'active_support/descendants_tracker' module ActiveModel + # == Active Model Observers Activation module Observing extend ActiveSupport::Concern @@ -17,9 +18,7 @@ module ActiveModel end module ClassMethods - # == Active Model Observers Activation - # - # Activates the observers assigned. Examples: + # Activates the observers assigned. # # class ORM # include ActiveModel::Observing @@ -35,34 +34,95 @@ module ActiveModel # ORM.observers = Cacher, GarbageCollector # # Note: Setting this does not instantiate the observers yet. - # +instantiate_observers+ is called during startup, and before + # instantiate_observers is called during startup, and before # each development request. def observers=(*values) observers.replace(values.flatten) end - # Gets an array of observers observing this model. - # The array also provides +enable+ and +disable+ methods - # that allow you to selectively enable and disable observers. - # (see ActiveModel::ObserverArray.enable and - # ActiveModel::ObserverArray.disable for more on this) + # Gets an array of observers observing this model. The array also provides + # +enable+ and +disable+ methods that allow you to selectively enable and + # disable observers (see ActiveModel::ObserverArray.enable and + # ActiveModel::ObserverArray.disable for more on this). + # + # class ORM + # include ActiveModel::Observing + # end + # + # ORM.observers = :cacher, :garbage_collector + # ORM.observers # => [:cacher, :garbage_collector] + # ORM.observers.class # => ActiveModel::ObserverArray def observers @observers ||= ObserverArray.new(self) end - # Gets the current observer instances. + # Returns the current observer instances. + # + # class Foo + # include ActiveModel::Observing + # + # attr_accessor :status + # end + # + # class FooObserver < ActiveModel::Observer + # def on_spec(record, *args) + # record.status = true + # end + # end + # + # Foo.observers = FooObserver + # Foo.instantiate_observers + # + # Foo.observer_instances # => [#] def observer_instances @observer_instances ||= [] end # Instantiate the global observers. + # + # class Foo + # include ActiveModel::Observing + # + # attr_accessor :status + # end + # + # class FooObserver < ActiveModel::Observer + # def on_spec(record, *args) + # record.status = true + # end + # end + # + # Foo.observers = FooObserver + # + # foo = Foo.new + # foo.status = false + # foo.notify_observers(:on_spec) + # foo.status # => false + # + # Foo.instantiate_observers # => [FooObserver] + # + # foo = Foo.new + # foo.status = false + # foo.notify_observers(:on_spec) + # foo.status # => true def instantiate_observers observers.each { |o| instantiate_observer(o) } end - # Add a new observer to the pool. - # The new observer needs to respond to 'update', otherwise it - # raises an +ArgumentError+ exception. + # Add a new observer to the pool. The new observer needs to respond to + # update, otherwise it raises an +ArgumentError+ exception. + # + # class Foo + # include ActiveModel::Observing + # end + # + # class FooObserver < ActiveModel::Observer + # end + # + # Foo.add_observer(FooObserver.instance) + # + # Foo.observers_instance + # # => [#] def add_observer(observer) unless observer.respond_to? :update raise ArgumentError, "observer needs to respond to 'update'" @@ -70,16 +130,47 @@ module ActiveModel observer_instances << observer end - # Notify list of observers of a change. + # Fires notifications to model's observers. + # + # def save + # notify_observers(:before_save) + # ... + # notify_observers(:after_save) + # end + # + # Custom notifications can be sent in a similar fashion: + # + # notify_observers(:custom_notification, :foo) + # + # This will call custom_notification, passing as arguments + # the current object and :foo. def notify_observers(*args) observer_instances.each { |observer| observer.update(*args) } end - # Total number of observers. + # Returns the total number of instantiated observers. + # + # class Foo + # include ActiveModel::Observing + # + # attr_accessor :status + # end + # + # class FooObserver < ActiveModel::Observer + # def on_spec(record, *args) + # record.status = true + # end + # end + # + # Foo.observers = FooObserver + # Foo.observers_count # => 0 + # Foo.instantiate_observers + # Foo.observers_count # => 1 def observers_count observer_instances.size end + # count_observers is deprecated. Use #observers_count. def count_observers msg = "count_observers is deprecated in favor of observers_count" ActiveSupport::Deprecation.warn(msg) @@ -110,21 +201,30 @@ module ActiveModel end end - # Fires notifications to model's observers + # Notify a change to the list of observers. + # + # class Foo + # include ActiveModel::Observing # - # def save - # notify_observers(:before_save) - # ... - # notify_observers(:after_save) + # attr_accessor :status # end # - # Custom notifications can be sent in a similar fashion: + # class FooObserver < ActiveModel::Observer + # def on_spec(record, *args) + # record.status = true + # end + # end # - # notify_observers(:custom_notification, :foo) + # Foo.observers = FooObserver + # Foo.instantiate_observers # => [FooObserver] # - # This will call +custom_notification+, passing as arguments - # the current object and :foo. + # foo = Foo.new + # foo.status = false + # foo.notify_observers(:on_spec) + # foo.status # => true # + # See ActiveModel::Observing::ClassMethods.notify_observers for more + # information. def notify_observers(method, *extra_args) self.class.notify_observers(method, self, *extra_args) end @@ -238,7 +338,7 @@ module ActiveModel # Send observed_method(object) if the method exists and # the observer is enabled for the given object's class. def update(observed_method, object, *extra_args, &block) #:nodoc: - return if !respond_to?(observed_method) || disabled_for?(object) + return if !respond_to?(observed_method) || disabled_for?(object) send(observed_method, object, *extra_args, &block) end -- cgit v1.2.3 From 1d537fdc47065d58ea268b6eac9593e559596431 Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 23:19:15 -0500 Subject: add :nodoc: to ActiveModel::Observing#inherited [ci skip] --- activemodel/lib/active_model/observing.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index 1114ac962a..aae0d3a2ef 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -195,7 +195,7 @@ module ActiveModel end # Notify observers when the observed class is subclassed. - def inherited(subclass) + def inherited(subclass) #:nodoc: super notify_observers :observed_class_inherited, subclass end -- cgit v1.2.3 From ab53cc7b2eee86152f20aea6c968d74d1c747c4e Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Mon, 30 Jul 2012 23:32:48 -0500 Subject: update ActiveModel::ObserverArray documentation [ci skip] --- activemodel/lib/active_model/observer_array.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb index 2a522e6f18..77bc0f71e3 100644 --- a/activemodel/lib/active_model/observer_array.rb +++ b/activemodel/lib/active_model/observer_array.rb @@ -5,13 +5,14 @@ module ActiveModel # a particular model class. class ObserverArray < Array attr_reader :model_class - def initialize(model_class, *args) + def initialize(model_class, *args) #:nodoc: @model_class = model_class super(*args) end - # Returns true if the given observer is disabled for the model class. - def disabled_for?(observer) + # Returns +true+ if the given observer is disabled for the model class, + # +false+ otherwise. + def disabled_for?(observer) #:nodoc: disabled_observers.include?(observer.class) end -- cgit v1.2.3 From db25ca7ec446e4142097d6cc4d80c21ea426398d Mon Sep 17 00:00:00 2001 From: Accessd Date: Tue, 31 Jul 2012 18:10:41 +0400 Subject: fix ActiveRecord::Associations::CollectionProxy documentation --- activerecord/lib/active_record/associations/collection_proxy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 2fb80fdc4c..89f24b2c43 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -346,7 +346,7 @@ module ActiveRecord # :call-seq: # delete_all() # - # Deletes all the records from the collection. For +has_many+ asssociations, + # Deletes all the records from the collection. For +has_many+ associations, # the deletion is done according to the strategy specified by the :dependent # option. Returns an array with the deleted records. # -- cgit v1.2.3 From cf21657f6e55346fa2f5555926f3f6a1e199de65 Mon Sep 17 00:00:00 2001 From: David Celis Date: Tue, 31 Jul 2012 09:17:16 -0700 Subject: Update I18n guide with details on multilingual Inflector [ci skip] Sorry; I forgot about the guides when I submitted this patch. Signed-off-by: David Celis --- guides/source/i18n.textile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guides/source/i18n.textile b/guides/source/i18n.textile index 8ad6ee4b73..f67d487eee 100644 --- a/guides/source/i18n.textile +++ b/guides/source/i18n.textile @@ -405,6 +405,10 @@ So that would give you: TIP: Right now you might need to add some more date/time formats in order to make the I18n backend work as expected (at least for the 'pirate' locale). Of course, there's a great chance that somebody already did all the work by *translating Rails' defaults for your locale*. See the "rails-i18n repository at Github":https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale for an archive of various locale files. When you put such file(s) in +config/locales/+ directory, they will automatically be ready for use. +h4. Inflection Rules For Other Locales + +Rails 4.0 allows you to define inflection rules (such as rules for singularization and pluralization) for locales other than English. In +config/initializers/inflections.rb+, you can define these rules for multiple locales. The initializer contains a default example for specifying rules for Spanish; follow that format for other locales as you see fit. + h4. Localized Views Rails 2.3 introduces another convenient localization feature: localized views (templates). Let's say you have a _BooksController_ in your application. Your _index_ action renders content in +app/views/books/index.html.erb+ template. When you put a _localized variant_ of this template: *+index.es.html.erb+* in the same directory, Rails will render content in this template, when the locale is set to +:es+. When the locale is set to the default locale, the generic +index.html.erb+ view will be used. (Future Rails versions may well bring this _automagic_ localization to assets in +public+, etc.) -- cgit v1.2.3 From d9ac5b2b04e3453a602498753504373cff3e4824 Mon Sep 17 00:00:00 2001 From: David Celis Date: Tue, 31 Jul 2012 09:41:02 -0700 Subject: Fix a mistake in the I18n guide: English => Spanish [ci skip] Signed-off-by: David Celis --- guides/source/i18n.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/i18n.textile b/guides/source/i18n.textile index f67d487eee..c782539399 100644 --- a/guides/source/i18n.textile +++ b/guides/source/i18n.textile @@ -407,7 +407,7 @@ TIP: Right now you might need to add some more date/time formats in order to mak h4. Inflection Rules For Other Locales -Rails 4.0 allows you to define inflection rules (such as rules for singularization and pluralization) for locales other than English. In +config/initializers/inflections.rb+, you can define these rules for multiple locales. The initializer contains a default example for specifying rules for Spanish; follow that format for other locales as you see fit. +Rails 4.0 allows you to define inflection rules (such as rules for singularization and pluralization) for locales other than English. In +config/initializers/inflections.rb+, you can define these rules for multiple locales. The initializer contains a default example for specifying additional rules for English; follow that format for other locales as you see fit. h4. Localized Views -- cgit v1.2.3 From 7b7501b2e591718897f8d4a1d201b6d72f0fe7cd Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Tue, 31 Jul 2012 11:43:17 -0500 Subject: update ActiveModel::Observer documentation [ci skip] --- activemodel/lib/active_model/observing.rb | 53 +++++++++++++++++++------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index aae0d3a2ef..7da9246911 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -236,15 +236,15 @@ module ActiveModel # behavior outside the original class. This is a great way to reduce the # clutter that normally comes when the model class is burdened with # functionality that doesn't pertain to the core responsibility of the - # class. Example: + # class. # # class CommentObserver < ActiveModel::Observer # def after_save(comment) - # Notifications.comment("admin@do.com", "New comment was posted", comment).deliver + # Notifications.comment('admin@do.com', 'New comment was posted', comment).deliver # end # end # - # This Observer sends an email when a Comment#save is finished. + # This Observer sends an email when a Comment#save is finished. # # class ContactObserver < ActiveModel::Observer # def after_create(contact) @@ -261,44 +261,50 @@ module ActiveModel # == Observing a class that can't be inferred # # Observers will by default be mapped to the class with which they share a - # name. So CommentObserver will be tied to observing Comment, ProductManagerObserver - # to ProductManager, and so on. If you want to name your observer differently than - # the class you're interested in observing, you can use the Observer.observe - # class method which takes either the concrete class (Product) or a symbol for that - # class (:product): + # name. So CommentObserver will be tied to observing Comment, + # ProductManagerObserver to ProductManager, and so on. If + # you want to name your observer differently than the class you're interested + # in observing, you can use the Observer.observe class method which + # takes either the concrete class (Product) or a symbol for that + # class (:product): # # class AuditObserver < ActiveModel::Observer # observe :account # # def after_update(account) - # AuditTrail.new(account, "UPDATED") + # AuditTrail.new(account, 'UPDATED') # end # end # - # If the audit observer needs to watch more than one kind of object, this can be - # specified with multiple arguments: + # If the audit observer needs to watch more than one kind of object, this can + # be specified with multiple arguments: # # class AuditObserver < ActiveModel::Observer # observe :account, :balance # # def after_update(record) - # AuditTrail.new(record, "UPDATED") + # AuditTrail.new(record, 'UPDATED') # end # end # - # The AuditObserver will now act on both updates to Account and Balance by treating - # them both as records. + # The AuditObserver will now act on both updates to Account + # and Balance by treating them both as records. # - # If you're using an Observer in a Rails application with Active Record, be sure to - # read about the necessary configuration in the documentation for + # If you're using an Observer in a Rails application with Active Record, be + # sure to read about the necessary configuration in the documentation for # ActiveRecord::Observer. - # class Observer include Singleton extend ActiveSupport::DescendantsTracker class << self # Attaches the observer to the supplied model classes. + # + # class AuditObserver < ActiveModel::Observer + # observe :account, :balance + # end + # + # AuditObserver.observed_classes # => [Account, Balance] def observe(*models) models.flatten! models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model } @@ -307,6 +313,8 @@ module ActiveModel # Returns an array of Classes to observe. # + # AccountObserver.observed_classes # => [Account] + # # You can override this instead of using the +observe+ helper. # # class AuditObserver < ActiveModel::Observer @@ -318,8 +326,11 @@ module ActiveModel Array(observed_class) end - # The class observed by default is inferred from the observer's class name: - # assert_equal Person, PersonObserver.observed_class + # Returns the class observed by default. It's inferred from the observer's + # class name. + # + # PersonObserver.observed_class # => Person + # AccountObserver.observed_class # => Account def observed_class name[/(.*)Observer/, 1].try :constantize end @@ -327,7 +338,7 @@ module ActiveModel # Start observing the declared classes and their subclasses. # Called automatically by the instance method. - def initialize + def initialize #:nodoc: observed_classes.each { |klass| add_observer!(klass) } end @@ -355,7 +366,7 @@ module ActiveModel end # Returns true if notifications are disabled for this object. - def disabled_for?(object) + def disabled_for?(object) #:nodoc: klass = object.class return false unless klass.respond_to?(:observers) klass.observers.disabled_for?(self) -- cgit v1.2.3 From c5fcc9ad1cd95854c3c8129f453982c6acd8fd61 Mon Sep 17 00:00:00 2001 From: Robert Pankowecki Date: Tue, 31 Jul 2012 20:22:44 +0200 Subject: Update #resources documentation [ci skip] --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0a65b4dbcc..a4f868593a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1186,6 +1186,10 @@ module ActionDispatch # sekret_comment PATCH/PUT /comments/:id(.:format) # sekret_comment DELETE /comments/:id(.:format) # + # [:format] + # Allows you to specify default value for optional +format+ segment + # or disable it if you supply +false+ + # # === Examples # # # routes call Admin::PostsController -- cgit v1.2.3 From 8453addedcea6e42a5df3d241225a32698121072 Mon Sep 17 00:00:00 2001 From: Robert Pankowecki Date: Tue, 31 Jul 2012 20:28:02 +0200 Subject: Update #match documentation [ci skip] --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index a4f868593a..4c4d12998f 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -404,6 +404,10 @@ module ActionDispatch # # # Matches any request starting with 'path' # match 'path' => 'c#a', :anchor => false + # + # [:format] + # Allows you to specify default value for optional +format+ segment + # or disable it if you supply +false+ def match(path, options=nil) end -- cgit v1.2.3 From cbcfbdd078c1f69f65a31d87b218fb41f495ce0f Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Tue, 31 Jul 2012 14:16:46 -0500 Subject: fix punctuation in #resources and #match documentation [ci skip] --- actionpack/lib/action_dispatch/routing/mapper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 4c4d12998f..90b45d6502 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -406,8 +406,8 @@ module ActionDispatch # match 'path' => 'c#a', :anchor => false # # [:format] - # Allows you to specify default value for optional +format+ segment - # or disable it if you supply +false+ + # Allows you to specify the default value for optional +format+ + # segment or disable it if you supply +false+. def match(path, options=nil) end @@ -1191,8 +1191,8 @@ module ActionDispatch # sekret_comment DELETE /comments/:id(.:format) # # [:format] - # Allows you to specify default value for optional +format+ segment - # or disable it if you supply +false+ + # Allows you to specify the default value for optional +format+ + # segment or disable it if you supply +false+. # # === Examples # -- cgit v1.2.3 From 3fb0100ef893b8cf229e82ce264b426e0c961eb1 Mon Sep 17 00:00:00 2001 From: Franco Catena Date: Wed, 1 Aug 2012 10:32:08 -0300 Subject: Fix string interpolation in belongs_to docs --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 6124fe315f..8ab525246a 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1408,7 +1408,7 @@ module ActiveRecord # belongs_to :person, :primary_key => "name", :foreign_key => "person_name" # belongs_to :author, :class_name => "Person", :foreign_key => "author_id" # belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", - # :conditions => 'discounts > #{payments_count}' + # :conditions => "discounts > #{payments_count}" # belongs_to :attachable, :polymorphic => true # belongs_to :project, :readonly => true # belongs_to :post, :counter_cache => true -- cgit v1.2.3 From eb66eadfc627cbe6bfebdff7d5a1dfb01f00cd21 Mon Sep 17 00:00:00 2001 From: Mikhail Dieterle Date: Thu, 2 Aug 2012 20:02:37 +0300 Subject: fixed wrong route for creating new post [ci skip] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now there is error ```No route matches [POST] “/posts”``` --- guides/source/getting_started.textile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/guides/source/getting_started.textile b/guides/source/getting_started.textile index 8d7c0d4bea..22da369a2a 100644 --- a/guides/source/getting_started.textile +++ b/guides/source/getting_started.textile @@ -373,7 +373,7 @@ Edit the +form_for+ line inside +app/views/posts/new.html.erb+ to look like this In this example, a +Hash+ object is passed to the +:url+ option. What Rails will do with this is that it will point the form to the +create+ action of the current controller, the +PostsController+, and will send a +POST+ request to that route. For this to work, you will need to add a route to +config/routes.rb+, right underneath the one for "posts/new": -post "posts/create" +post "posts" => "posts#create" By using the +post+ method rather than the +get+ method, Rails will define a route that will only respond to POST methods. The POST method is the typical method used by forms all over the web. @@ -1064,13 +1064,13 @@ received an error before. # rake routes - posts GET /posts(.:format) posts#index - posts_new GET /posts/new(.:format) posts#new -posts_create POST /posts/create(.:format) posts#create - GET /posts/:id(.:format) posts#show - GET /posts/:id/edit(.:format) posts#edit - PUT /posts/:id(.:format) posts#update - root / welcome#index + posts GET /posts(.:format) posts#index +posts_new GET /posts/new(.:format) posts#new + POST /posts(.:format) posts#create + GET /posts/:id(.:format) posts#show + GET /posts/:id/edit(.:format) posts#edit + PUT /posts/:id(.:format) posts#update + root / welcome#index To fix this, open +config/routes.rb+ and modify the +get "posts/:id"+ @@ -1175,7 +1175,7 @@ declaring separate routes with the appropriate verbs into get "posts" => "posts#index" get "posts/new" -post "posts/create" +post "posts" => "posts#create" get "posts/:id" => "posts#show", :as => :post get "posts/:id/edit" => "posts#edit" put "posts/:id" => "posts#update" -- cgit v1.2.3 From f8d1b52a4ffe56b8c6652b9cb0b7e9f8027fc05a Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Thu, 2 Aug 2012 14:20:49 -0400 Subject: Audit the usage of the word "JavaScript" --- guides/source/action_view_overview.textile | 2 +- guides/source/ajax_on_rails.textile | 2 +- guides/source/command_line.textile | 2 +- guides/source/configuring.textile | 2 +- guides/source/security.textile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/guides/source/action_view_overview.textile b/guides/source/action_view_overview.textile index fdfa97effa..1fd98a5bbe 100644 --- a/guides/source/action_view_overview.textile +++ b/guides/source/action_view_overview.textile @@ -785,7 +785,7 @@ h5. content_for Calling +content_for+ stores a block of markup in an identifier for later use. You can make subsequent calls to the stored content in other templates or the layout by passing the identifier as an argument to +yield+. -For example, let's say we have a standard application layout, but also a special page that requires certain Javascript that the rest of the site doesn't need. We can use +content_for+ to include this Javascript on our special page without fattening up the rest of the site. +For example, let's say we have a standard application layout, but also a special page that requires certain JavaScript that the rest of the site doesn't need. We can use +content_for+ to include this JavaScript on our special page without fattening up the rest of the site. *app/views/layouts/application.html.erb* diff --git a/guides/source/ajax_on_rails.textile b/guides/source/ajax_on_rails.textile index 26e0270a31..67b0c9f0d3 100644 --- a/guides/source/ajax_on_rails.textile +++ b/guides/source/ajax_on_rails.textile @@ -28,7 +28,7 @@ the +ul+ node. h4. Asynchronous JavaScript + XML AJAX means Asynchronous JavaScript + XML. Asynchronous means that the page is not -reloaded, the request made is separate from the regular page request. Javascript +reloaded, the request made is separate from the regular page request. JavaScript is used to evaluate the response and the XML part is a bit misleading as XML is not required, you respond to the HTTP request with JSON or regular HTML as well. diff --git a/guides/source/command_line.textile b/guides/source/command_line.textile index 1ed0c48933..39b75c2781 100644 --- a/guides/source/command_line.textile +++ b/guides/source/command_line.textile @@ -160,7 +160,7 @@ $ rails generate controller Greetings hello create app/assets/stylesheets/greetings.css.scss -What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a view file, a functional test file, a helper for the view, a javascript file and a stylesheet file. +What all did this generate? It made sure a bunch of directories were in our application, and created a controller file, a view file, a functional test file, a helper for the view, a JavaScript file and a stylesheet file. Check out the controller and modify it a little (in +app/controllers/greetings_controller.rb+): diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile index e7272a51b7..25f69f1ab1 100644 --- a/guides/source/configuring.textile +++ b/guides/source/configuring.textile @@ -186,7 +186,7 @@ The full set of methods that can be used in this block are as follows: * +force_plural+ allows pluralized model names. Defaults to +false+. * +helper+ defines whether or not to generate helpers. Defaults to +true+. * +integration_tool+ defines which integration tool to use. Defaults to +nil+. -* +javascripts+ turns on the hook for javascripts in generators. Used in Rails for when the +scaffold+ generator is run. Defaults to +true+. +* +javascripts+ turns on the hook for JavaScripts in generators. Used in Rails for when the +scaffold+ generator is run. Defaults to +true+. * +javascript_engine+ configures the engine to be used (for eg. coffee) when generating assets. Defaults to +nil+. * +orm+ defines which orm to use. Defaults to +false+ and will use Active Record by default. * +performance_tool+ defines which performance tool to use. Defaults to +nil+. diff --git a/guides/source/security.textile b/guides/source/security.textile index 8879122b66..49e5da6bb7 100644 --- a/guides/source/security.textile +++ b/guides/source/security.textile @@ -608,7 +608,7 @@ This URL passes the filter because the regular expression matches – the second link_to "Homepage", @user.homepage -The link looks innocent to visitors, but when it's clicked, it will execute the javascript function "exploit_code" or any other javascript the attacker provides. +The link looks innocent to visitors, but when it's clicked, it will execute the JavaScript function "exploit_code" or any other JavaScript the attacker provides. To fix the regular expression, \A and \z should be used instead of ^ and $, like so: -- cgit v1.2.3 From ad9b6a3f9415a3308b2f9aacccf1a9ae8fe4ec75 Mon Sep 17 00:00:00 2001 From: Robert Pankowecki Date: Thu, 2 Aug 2012 23:47:02 +0200 Subject: Fix ActiveModel::Serializers::Xml#to_xml reference Link to ActiveRecord::Serialization#to_xml for more details --- activemodel/lib/active_model/serializers/xml.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 96ae47cec1..56873538fd 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -182,7 +182,7 @@ module ActiveModel # # To include associations use :include. # - # For further documentation, see activerecord/lib/active_record/serializers/xml_serializer.xml. + # For further documentation, see ActiveRecord::Serialization#to_xml def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end -- cgit v1.2.3 From a2a73c5abbad8f2c58df90695b03ddf1363b949e Mon Sep 17 00:00:00 2001 From: Mikhail Dieterle Date: Fri, 3 Aug 2012 21:58:15 +0300 Subject: Update guides/source/asset_pipeline.textile --- guides/source/asset_pipeline.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/source/asset_pipeline.textile b/guides/source/asset_pipeline.textile index d0952fcf29..4914327c4e 100644 --- a/guides/source/asset_pipeline.textile +++ b/guides/source/asset_pipeline.textile @@ -651,7 +651,7 @@ WARNING: If you are upgrading an existing application and intend to use this opt h3. Assets Cache Store -Sprockets uses the default Rails cache store will be used to cache assets in development and production. This can be changed by setting +config.assets.cache_store+. +The default Rails cache store will be used by Sprockets to cache assets in development and production. This can be changed by setting +config.assets.cache_store+. config.assets.cache_store = :memory_store -- cgit v1.2.3 From 1a8e000339067a128bc1b941d0612eae5f484b5d Mon Sep 17 00:00:00 2001 From: Ace Suares Date: Fri, 3 Aug 2012 21:36:10 -0400 Subject: added info about an error that mysql gives when rails@localhost has a password; removed reference to activerecord/test/connections, which isn't there anymore --- guides/source/contributing_to_ruby_on_rails.textile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/guides/source/contributing_to_ruby_on_rails.textile b/guides/source/contributing_to_ruby_on_rails.textile index 35ec988c5e..9ae627c237 100644 --- a/guides/source/contributing_to_ruby_on_rails.textile +++ b/guides/source/contributing_to_ruby_on_rails.textile @@ -202,6 +202,8 @@ $ cd activerecord $ bundle exec rake mysql:build_databases +NOTE: If you get an error like "Access denied for user 'rails'@'localhost' (using password: YES)" then you most likely have a rails user in the mysql database, that uses a password, or you have a password specified in the my.cnf file of mysql. + PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account @@ -219,7 +221,7 @@ NOTE: Using the rake task to create the test databases ensures they have the cor NOTE: You'll see the following warning (or localized warning) during activating HStore extension in PostgreSQL 9.1.x or earlier: "WARNING: => is deprecated as an operator". -If you’re using another database, check the files under +activerecord/test/connections+ for default connection information. You can edit these files to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails. +If you’re using another database, check the file +activerecord/test/config.yml+ or +activerecord/test/config.example.yml+ for default connection information. You can edit +activerecord/test/config.yml+ to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails. You can now run the tests as you did for +sqlite3+. The tasks are respectively -- cgit v1.2.3 From ad088f096a31b945152bfb0740acba87c85f144b Mon Sep 17 00:00:00 2001 From: Andrew Vit Date: Sat, 4 Aug 2012 02:05:16 -0700 Subject: Corrected info about asset pipeline default paths --- guides/source/asset_pipeline.textile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/guides/source/asset_pipeline.textile b/guides/source/asset_pipeline.textile index 4914327c4e..42b5d102e7 100644 --- a/guides/source/asset_pipeline.textile +++ b/guides/source/asset_pipeline.textile @@ -121,7 +121,7 @@ h5. Search paths When a file is referenced from a manifest or a helper, Sprockets searches the three default asset locations for it. -The default locations are: +app/assets/images+ and the subdirectories +javascripts+ and +stylesheets+ in all three asset locations. +The default locations are: +app/assets/images+ and the subdirectories +javascripts+ and +stylesheets+ in all three asset locations, but these subdirectories are not special. Any path under +assets/*+ will be searched. For example, these files: @@ -129,6 +129,7 @@ For example, these files: app/assets/javascripts/home.js lib/assets/javascripts/moovinator.js vendor/assets/javascripts/slider.js +vendor/assets/somepackage/phonebox.js would be referenced in a manifest like this: @@ -137,6 +138,7 @@ would be referenced in a manifest like this: //= require home //= require moovinator //= require slider +//= require phonebox Assets inside subdirectories can also be accessed. @@ -153,13 +155,13 @@ is referenced as: You can view the search path by inspecting +Rails.application.config.assets.paths+ in the Rails console. -Additional (fully qualified) paths can be added to the pipeline in +config/application.rb+. For example: +Besides the standard +assets/*+ paths, additional (fully qualified) paths can be added to the pipeline in +config/application.rb+. For example: -config.assets.paths << Rails.root.join("app", "assets", "flash") +config.assets.paths << Rails.root.join("lib", "videoplayer", "flash") -Paths are traversed in the order that they occur in the search path. +Paths are traversed in the order that they occur in the search path. By default, this means the files in +app/assets+ take precedence, and will mask corresponding paths in +lib+ and +vendor+. It is important to note that files you want to reference outside a manifest must be added to the precompile array or they will not be available in the production environment. -- cgit v1.2.3 From 4ae72a931ea8ef8f5994b3325a4e431cf2cb2f39 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sat, 4 Aug 2012 01:12:26 +0530 Subject: Revert "Fix string interpolation in belongs_to docs" This reverts commit 3fb0100ef893b8cf229e82ce264b426e0c961eb1. --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 8ab525246a..6124fe315f 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1408,7 +1408,7 @@ module ActiveRecord # belongs_to :person, :primary_key => "name", :foreign_key => "person_name" # belongs_to :author, :class_name => "Person", :foreign_key => "author_id" # belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", - # :conditions => "discounts > #{payments_count}" + # :conditions => 'discounts > #{payments_count}' # belongs_to :attachable, :polymorphic => true # belongs_to :project, :readonly => true # belongs_to :post, :counter_cache => true -- cgit v1.2.3 From b51201242aaf77c6db5a9b2f72e433c521df79c5 Mon Sep 17 00:00:00 2001 From: Vijay Dev Date: Sat, 4 Aug 2012 14:30:21 +0530 Subject: copy edits [ci skip] --- actionpack/lib/action_dispatch/routing/mapper.rb | 4 ++-- activemodel/lib/active_model/serializers/xml.rb | 2 +- guides/source/configuring.textile | 2 +- guides/source/contributing_to_ruby_on_rails.textile | 6 ------ 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 90b45d6502..f5e1450f8a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -407,7 +407,7 @@ module ActionDispatch # # [:format] # Allows you to specify the default value for optional +format+ - # segment or disable it if you supply +false+. + # segment or disable it by supplying +false+. def match(path, options=nil) end @@ -1192,7 +1192,7 @@ module ActionDispatch # # [:format] # Allows you to specify the default value for optional +format+ - # segment or disable it if you supply +false+. + # segment or disable it by supplying +false+. # # === Examples # diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index 56873538fd..016d821fdf 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -182,7 +182,7 @@ module ActiveModel # # To include associations use :include. # - # For further documentation, see ActiveRecord::Serialization#to_xml + # For further documentation, see ActiveRecord::Serialization#to_xml def to_xml(options = {}, &block) Serializer.new(self, options).serialize(&block) end diff --git a/guides/source/configuring.textile b/guides/source/configuring.textile index 25f69f1ab1..cc5c352df4 100644 --- a/guides/source/configuring.textile +++ b/guides/source/configuring.textile @@ -186,7 +186,7 @@ The full set of methods that can be used in this block are as follows: * +force_plural+ allows pluralized model names. Defaults to +false+. * +helper+ defines whether or not to generate helpers. Defaults to +true+. * +integration_tool+ defines which integration tool to use. Defaults to +nil+. -* +javascripts+ turns on the hook for JavaScripts in generators. Used in Rails for when the +scaffold+ generator is run. Defaults to +true+. +* +javascripts+ turns on the hook for JavaScript files in generators. Used in Rails for when the +scaffold+ generator is run. Defaults to +true+. * +javascript_engine+ configures the engine to be used (for eg. coffee) when generating assets. Defaults to +nil+. * +orm+ defines which orm to use. Defaults to +false+ and will use Active Record by default. * +performance_tool+ defines which performance tool to use. Defaults to +nil+. diff --git a/guides/source/contributing_to_ruby_on_rails.textile b/guides/source/contributing_to_ruby_on_rails.textile index 9ae627c237..dd43ef795f 100644 --- a/guides/source/contributing_to_ruby_on_rails.textile +++ b/guides/source/contributing_to_ruby_on_rails.textile @@ -184,10 +184,6 @@ We need first to delete +.bundle/config+ because Bundler remembers in that 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: - -mysql -u root mysql -p - - mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost'; @@ -202,8 +198,6 @@ $ cd activerecord $ bundle exec rake mysql:build_databases -NOTE: If you get an error like "Access denied for user 'rails'@'localhost' (using password: YES)" then you most likely have a rails user in the mysql database, that uses a password, or you have a password specified in the my.cnf file of mysql. - PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account -- cgit v1.2.3