From b9bb240a2b5abc0b6704b1a1552a31c4f1d96f34 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 14:02:14 -0800 Subject: just mutate the ast, fewer lasgns --- activerecord/lib/active_record/relation/query_methods.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 08b61c9752..dce9ac4808 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -225,14 +225,13 @@ module ActiveRecord test = eqls.inject(eqls.shift) do |memo, expr| memo.or(expr) end - arel = arel.where(test) + arel.where(test) end (wheres - equalities).each do |where| where = Arel.sql(where) if String === where - arel = arel.where(Arel::Nodes::Grouping.new(where)) + arel.where(Arel::Nodes::Grouping.new(where)) end - arel end def build_where(opts, other = []) -- cgit v1.2.3 From 4d5f9a07658f610c34851ceca2a0e25e5ad83503 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 14:44:42 -0800 Subject: remove lasgn since AST is mutated --- .../class_methods/join_dependency/join_association.rb | 10 ++++++++-- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 98536d23bc..4839068f6d 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -135,9 +135,15 @@ module ActiveRecord conditions << process_conditions(options[:conditions], aliased_table_name) end - join = relation.join(target_table, join_type) + ands = relation.create_and(conditions) - join.on(*conditions) + join = relation.create_join( + relation.froms.first, + target_table, + relation.create_on(ands), + join_type) + + relation.from join end def join_has_and_belongs_to_many_to(relation) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index dce9ac4808..51a39be065 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -266,7 +266,7 @@ module ActiveRecord # FIXME: refactor this to build an AST join_dependency.join_associations.each do |association| - manager = association.join_to(manager) + association.join_to(manager) end return manager unless join_ast -- cgit v1.2.3 From 64ba043544008a92a4fe1940e836a7dfa4ca3f11 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 15:13:51 -0800 Subject: explicitly set prefix --- .../associations/class_methods/join_dependency/join_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index 4839068f6d..f1b923e98b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -22,7 +22,7 @@ module ActiveRecord attr_reader :aliased_prefix, :aliased_table_name delegate :options, :through_reflection, :source_reflection, :to => :reflection - delegate :table, :table_name, :to => :parent, :prefix => true + delegate :table, :table_name, :to => :parent, :prefix => :parent def initialize(reflection, join_dependency, parent = nil) reflection.check_validity! -- cgit v1.2.3 From 8924018d5994cdc71df3647897462ff82ce7bf37 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 15:27:10 -0800 Subject: move ivar to initialize, use triple dot rather than minus --- .../associations/class_methods/join_dependency/join_association.rb | 2 +- .../lib/active_record/connection_adapters/abstract/schema_statements.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index f1b923e98b..c552603097 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -37,6 +37,7 @@ module ActiveRecord @join_dependency = join_dependency @parent = parent @join_type = Arel::InnerJoin + @aliased_prefix = "t#{ join_dependency.join_parts.size }" # This must be done eagerly upon initialisation because the alias which is produced # depends on the state of the join dependency, but we want it to work the same way @@ -97,7 +98,6 @@ module ActiveRecord private def allocate_aliases - @aliased_prefix = "t#{ join_dependency.join_parts.size }" @aliased_table_name = aliased_table_name_for(table_name) if reflection.macro == :has_and_belongs_to_many diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index d4aefada22..5b9c48bafa 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -12,7 +12,7 @@ module ActiveRecord # Truncates a table alias according to the limits of the current adapter. def table_alias_for(table_name) - table_name[0..table_alias_length-1].gsub(/\./, '_') + table_name[0...table_alias_length].gsub(/\./, '_') end # def tables(name = nil) end -- cgit v1.2.3 From 9e16254b4661f0ec55f035f62e70148827dcdf56 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 16:26:43 -0800 Subject: reduce method calls --- activerecord/lib/active_record/reflection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index a07c321960..fe4b518826 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -248,7 +248,7 @@ module ActiveRecord end def has_inverse? - !@options[:inverse_of].nil? + @options[:inverse_of] end def inverse_of -- cgit v1.2.3 From de708447f4bc2ae692440bbac235f9fe04f0702f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 17:01:15 -0800 Subject: combine regexp --- .../lib/active_record/associations/class_methods/join_dependency.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index b6d85a7c7d..6be947df41 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -66,10 +66,8 @@ module ActiveRecord end def count_aliases_from_string(join_sql, name) - # Table names - join_sql.scan(/join(?:\s+\w+)?\s+#{name}\son/).size + - # Table aliases - join_sql.scan(/join(?:\s+\w+)?\s+\S+\s+#{name}\son/).size + # Table names + table aliases + join_sql.scan(/join(?:\s+\w+)?\s+(\S+\s+)?#{name}\son/).size end def instantiate(rows) -- cgit v1.2.3 From 9094cd2600ee0b4f6523dbb80a5fa9e43c81e0c0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 10 Dec 2010 17:03:32 -0800 Subject: just use the regexp directly --- .../associations/class_methods/join_dependency.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 6be947df41..5a0ff942ca 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -58,18 +58,16 @@ module ActiveRecord when Arel::Table right.name.downcase == name ? 1 : 0 when String - count_aliases_from_string(right.downcase, quoted_name) + # Table names + table aliases + right.downcase.scan( + /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ + ).size else 0 end }.sum end - def count_aliases_from_string(join_sql, name) - # Table names + table aliases - join_sql.scan(/join(?:\s+\w+)?\s+(\S+\s+)?#{name}\son/).size - end - def instantiate(rows) primary_key = join_base.aliased_primary_key parents = {} -- cgit v1.2.3 From c780cf2f024528da80c3b01a49ba9423add2e783 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 Dec 2010 01:50:21 -0200 Subject: Add named helper output to translated paths example --- railties/guides/source/routing.textile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index bc38e4a6e5..9dad6d3096 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -745,14 +745,14 @@ end Rails now creates routes to the +CategoriesController+. -|_.HTTP verb|_.Path |_.action | -|GET |/kategorien |index | -|GET |/kategorien/neu |new | -|POST |/kategorien |create | -|GET |/kategorien/1 |show | -|GET |/kategorien/:id/bearbeiten |edit | -|PUT |/kategorien/1 |update | -|DELETE |/kategorien/1 |destroy | +|_.HTTP verb|_.Path |_.action | .named helper | +|GET |/kategorien |index | categories_path | +|GET |/kategorien/neu |new | new_category_path | +|POST |/kategorien |create | categories_path | +|GET |/kategorien/1 |show | category_path | +|GET |/kategorien/:id/bearbeiten |edit | edit_category_path | +|PUT |/kategorien/1 |update | category_path | +|DELETE |/kategorien/1 |destroy | category_path | h4. Overriding the Singular Form -- cgit v1.2.3 From e4c252c119acb0e62a4832f904cdff3306094ee7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 Dec 2010 01:54:59 -0200 Subject: Add underline to header --- railties/guides/source/routing.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 9dad6d3096..3a3d1e050c 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -745,7 +745,7 @@ end Rails now creates routes to the +CategoriesController+. -|_.HTTP verb|_.Path |_.action | .named helper | +|_.HTTP verb|_.Path |_.action |_.named helper | |GET |/kategorien |index | categories_path | |GET |/kategorien/neu |new | new_category_path | |POST |/kategorien |create | categories_path | -- cgit v1.2.3 From 93af9ecf35063a372604c4d0fd168c3fd425e396 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 Dec 2010 02:02:09 -0200 Subject: Add named helper to photo controller example --- railties/guides/source/routing.textile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index 3a3d1e050c..d3f8e435ec 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -611,14 +611,14 @@ resources :photos, :controller => "images" will recognize incoming paths beginning with +/photos+ but route to the +Images+ controller: -|_. Verb |_.Path |_.action | -|GET |/photos |index | -|GET |/photos/new |new | -|POST |/photos |create | -|GET |/photos/1 |show | -|GET |/photos/1/edit |edit | -|PUT |/photos/1 |update | -|DELETE |/photos/1 |destroy | +|_. Verb |_.Path |_.action |_.named helper | +|GET |/photos |index | photos_path | +|GET |/photos/new |new | new_photo_path | +|POST |/photos |create | photos_path | +|GET |/photos/1 |show | photo_path | +|GET |/photos/1/edit |edit | edit_photo_path | +|PUT |/photos/1 |update | photo_path | +|DELETE |/photos/1 |destroy | photo_path | NOTE: Use +photos_path+, +new_photos_path+, etc. to generate paths for this resource. -- cgit v1.2.3 From f05238e1d2fe454e36ac9b90222395ae8c8cf48a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 Dec 2010 02:24:07 -0200 Subject: Tables style unification --- railties/guides/source/routing.textile | 126 ++++++++++++++++----------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile index d3f8e435ec..7af9779ac7 100644 --- a/railties/guides/source/routing.textile +++ b/railties/guides/source/routing.textile @@ -76,14 +76,14 @@ resources :photos creates seven different routes in your application, all mapping to the +Photos+ controller: -|_. Verb |_.Path |_.action |_.used for| -|GET |/photos |index |display a list of all photos| -|GET |/photos/new |new |return an HTML form for creating a new photo| -|POST |/photos |create |create a new photo| -|GET |/photos/:id |show |display a specific photo| -|GET |/photos/:id/edit |edit |return an HTML form for editing a photo| -|PUT |/photos/:id |update |update a specific photo| -|DELETE |/photos/:id |destroy |delete a specific photo| +|_. HTTP Verb |_.Path |_.action |_.used for | +|GET |/photos |index |display a list of all photos | +|GET |/photos/new |new |return an HTML form for creating a new photo | +|POST |/photos |create |create a new photo | +|GET |/photos/:id |show |display a specific photo | +|GET |/photos/:id/edit |edit |return an HTML form for editing a photo | +|PUT |/photos/:id |update |update a specific photo | +|DELETE |/photos/:id |destroy |delete a specific photo | h4. Paths and URLs @@ -130,13 +130,13 @@ resource :geocoder creates six different routes in your application, all mapping to the +Geocoders+ controller: -|_. Verb |_.Path |_.action |_.used for| -|GET |/geocoder/new |new |return an HTML form for creating the geocoder| -|POST |/geocoder |create |create the new geocoder| -|GET |/geocoder |show |display the one and only geocoder resource| -|GET |/geocoder/edit |edit |return an HTML form for editing the geocoder| -|PUT |/geocoder |update |update the one and only geocoder resource| -|DELETE |/geocoder |destroy |delete the geocoder resource| +|_.HTTP Verb |_.Path |_.action |_.used for | +|GET |/geocoder/new |new |return an HTML form for creating the geocoder | +|POST |/geocoder |create |create the new geocoder | +|GET |/geocoder |show |display the one and only geocoder resource | +|GET |/geocoder/edit |edit |return an HTML form for editing the geocoder | +|PUT |/geocoder |update |update the one and only geocoder resource | +|DELETE |/geocoder |destroy |delete the geocoder resource | NOTE: Because you might want to use the same controller for a singular route (+/account+) and a plural route (+/accounts/45+), singular resources map to plural controllers. @@ -160,14 +160,14 @@ end This will create a number of routes for each of the +posts+ and +comments+ controller. For +Admin::PostsController+, Rails will create: -|_. Verb |_.Path |_.action |_. helper | -|GET |/admin/posts |index | admin_posts_path | -|GET |/admin/posts/new |new | new_admin_posts_path | -|POST |/admin/posts |create | admin_posts_path | -|GET |/admin/posts/1 |show | admin_post_path(id) | -|GET |/admin/posts/1/edit |edit | edit_admin_post_path(id) | -|PUT |/admin/posts/1 |update | admin_post_path(id) | -|DELETE |/admin/posts/1 |destroy | admin_post_path(id) | +|_.HTTP Verb |_.Path |_.action |_.named helper | +|GET |/admin/posts |index | admin_posts_path | +|GET |/admin/posts/new |new | new_admin_posts_path | +|POST |/admin/posts |create | admin_posts_path | +|GET |/admin/posts/1 |show | admin_post_path(id) | +|GET |/admin/posts/1/edit |edit | edit_admin_post_path(id) | +|PUT |/admin/posts/1 |update | admin_post_path(id) | +|DELETE |/admin/posts/1 |destroy | admin_post_path(id) | If you want to route +/posts+ (without the prefix +/admin+) to +Admin::PostsController+, you could use @@ -199,14 +199,14 @@ resources :posts, :path => "/admin/posts" In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following paths map to +PostsController+: -|_. Verb |_.Path |_.action |_. helper | -|GET |/admin/posts |index | posts_path | -|GET |/admin/posts/new |new | posts_path | -|POST |/admin/posts |create | posts_path | -|GET |/admin/posts/1 |show | post_path(id) | -|GET |/admin/posts/1/edit |edit | edit_post_path(id) | -|PUT |/admin/posts/1 |update | post_path(id) | -|DELETE |/admin/posts/1 |destroy | post_path(id) | +|_.HTTP Verb |_.Path |_.action |_.named helper | +|GET |/admin/posts |index | posts_path | +|GET |/admin/posts/new |new | posts_path | +|POST |/admin/posts |create | posts_path | +|GET |/admin/posts/1 |show | post_path(id) | +|GET |/admin/posts/1/edit |edit | edit_post_path(id) | +|PUT |/admin/posts/1 |update | post_path(id) | +|DELETE |/admin/posts/1 |destroy | post_path(id) | h4. Nested Resources @@ -232,14 +232,14 @@ end In addition to the routes for magazines, this declaration will also route ads to an +AdsController+. The ad URLs require a magazine: -|_.Verb |_.Path |_.action |_.used for| -|GET |/magazines/1/ads |index |display a list of all ads for a specific magazine| -|GET |/magazines/1/ads/new |new |return an HTML form for creating a new ad belonging to a specific magazine| -|POST |/magazines/1/ads |create |create a new ad belonging to a specific magazine| -|GET |/magazines/1/ads/1 |show |display a specific ad belonging to a specific magazine| -|GET |/magazines/1/ads/1/edit |edit |return an HTML form for editing an ad belonging to a specific magazine| -|PUT |/magazines/1/ads/1 |update |update a specific ad belonging to a specific magazine| -|DELETE |/magazines/1/ads/1 |destroy |delete a specific ad belonging to a specific magazine| +|_.HTTP Verb |_.Path |_.action |_.used for | +|GET |/magazines/1/ads |index |display a list of all ads for a specific magazine | +|GET |/magazines/1/ads/new |new |return an HTML form for creating a new ad belonging to a specific magazine | +|POST |/magazines/1/ads |create |create a new ad belonging to a specific magazine | +|GET |/magazines/1/ads/1 |show |display a specific ad belonging to a specific magazine | +|GET |/magazines/1/ads/1/edit |edit |return an HTML form for editing an ad belonging to a specific magazine | +|PUT |/magazines/1/ads/1 |update |update a specific ad belonging to a specific magazine | +|DELETE |/magazines/1/ads/1 |destroy |delete a specific ad belonging to a specific magazine | This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+. These helpers take an instance of Magazine as the first parameter (+magazine_ads_url(@magazine)+). @@ -611,14 +611,14 @@ resources :photos, :controller => "images" will recognize incoming paths beginning with +/photos+ but route to the +Images+ controller: -|_. Verb |_.Path |_.action |_.named helper | -|GET |/photos |index | photos_path | -|GET |/photos/new |new | new_photo_path | -|POST |/photos |create | photos_path | -|GET |/photos/1 |show | photo_path | -|GET |/photos/1/edit |edit | edit_photo_path | -|PUT |/photos/1 |update | photo_path | -|DELETE |/photos/1 |destroy | photo_path | +|_.HTTP Verb |_.Path |_.action |_.named helper | +|GET |/photos |index | photos_path | +|GET |/photos/new |new | new_photo_path | +|POST |/photos |create | photos_path | +|GET |/photos/1 |show | photo_path(id) | +|GET |/photos/1/edit |edit | edit_photo_path(id) | +|PUT |/photos/1 |update | photo_path(id) | +|DELETE |/photos/1 |destroy | photo_path(id) | NOTE: Use +photos_path+, +new_photos_path+, etc. to generate paths for this resource. @@ -653,14 +653,14 @@ resources :photos, :as => "images" will recognize incoming paths beginning with +/photos+ and route the requests to +PhotosController+, but use the value of the :as option to name the helpers. -|_.HTTP verb|_.Path |_.action |_.named helper | -|GET |/photos |index | images_path | -|GET |/photos/new |new | new_image_path | -|POST |/photos |create | images_path | -|GET |/photos/1 |show | image_path | -|GET |/photos/1/edit |edit | edit_image_path | -|PUT |/photos/1 |update | image_path | -|DELETE |/photos/1 |destroy | image_path | +|_.HTTP verb|_.Path |_.action |_.named helper | +|GET |/photos |index | images_path | +|GET |/photos/new |new | new_image_path | +|POST |/photos |create | images_path | +|GET |/photos/1 |show | image_path(id) | +|GET |/photos/1/edit |edit | edit_image_path(id) | +|PUT |/photos/1 |update | image_path(id) | +|DELETE |/photos/1 |destroy | image_path(id) | h4. Overriding the +new+ and +edit+ Segments @@ -745,14 +745,14 @@ end Rails now creates routes to the +CategoriesController+. -|_.HTTP verb|_.Path |_.action |_.named helper | -|GET |/kategorien |index | categories_path | -|GET |/kategorien/neu |new | new_category_path | -|POST |/kategorien |create | categories_path | -|GET |/kategorien/1 |show | category_path | -|GET |/kategorien/:id/bearbeiten |edit | edit_category_path | -|PUT |/kategorien/1 |update | category_path | -|DELETE |/kategorien/1 |destroy | category_path | +|_.HTTP verb|_.Path |_.action |_.named helper | +|GET |/kategorien |index | categories_path | +|GET |/kategorien/neu |new | new_category_path | +|POST |/kategorien |create | categories_path | +|GET |/kategorien/1 |show | category_path(id) | +|GET |/kategorien/1/bearbeiten |edit | edit_category_path(id) | +|PUT |/kategorien/1 |update | category_path(id) | +|DELETE |/kategorien/1 |destroy | category_path(id) | h4. Overriding the Singular Form -- cgit v1.2.3 From 7891de893951c780a1732747d430c33e998dd573 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 10 Dec 2010 14:42:10 +0100 Subject: Allow to generate namespaced generators [#6140 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- .../rails/generator/generator_generator.rb | 4 +-- .../test/generators/generator_generator_test.rb | 39 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/rails/generator/generator_generator.rb b/railties/lib/rails/generators/rails/generator/generator_generator.rb index 5b5d1884bc..3e0a442bda 100644 --- a/railties/lib/rails/generators/rails/generator/generator_generator.rb +++ b/railties/lib/rails/generators/rails/generator/generator_generator.rb @@ -14,9 +14,9 @@ module Rails def generator_dir if options[:namespace] - File.join("lib", "generators", file_name) + File.join("lib", "generators", regular_class_path, file_name) else - File.join("lib", "generators") + File.join("lib", "generators", regular_class_path) end end diff --git a/railties/test/generators/generator_generator_test.rb b/railties/test/generators/generator_generator_test.rb index 26f975a191..f4c975fc18 100644 --- a/railties/test/generators/generator_generator_test.rb +++ b/railties/test/generators/generator_generator_test.rb @@ -17,4 +17,43 @@ class GeneratorGeneratorTest < Rails::Generators::TestCase assert_file "lib/generators/awesome/awesome_generator.rb", /class AwesomeGenerator < Rails::Generators::NamedBase/ end + + def test_namespaced_generator_skeleton + run_generator ["rails/awesome"] + + %w( + lib/generators/rails/awesome + lib/generators/rails/awesome/USAGE + lib/generators/rails/awesome/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/rails/awesome/awesome_generator.rb", + /class Rails::AwesomeGenerator < Rails::Generators::NamedBase/ + end + + def test_generator_skeleton_is_created_without_file_name_namespace + run_generator ["awesome", "--namespace", "false"] + + %w( + lib/generators/ + lib/generators/USAGE + lib/generators/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/awesome_generator.rb", + /class AwesomeGenerator < Rails::Generators::NamedBase/ + end + + def test_namespaced_generator_skeleton_without_file_name_namespace + run_generator ["rails/awesome", "--namespace", "false"] + + %w( + lib/generators/rails + lib/generators/rails/USAGE + lib/generators/rails/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/rails/awesome_generator.rb", + /class Rails::AwesomeGenerator < Rails::Generators::NamedBase/ + end end -- cgit v1.2.3 From 307443972c5f6de959a5401eec76ca327484b10c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 10 Dec 2010 22:16:34 +0100 Subject: Skip creating migration if --skip option is passed to model generator [#6144 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- railties/lib/rails/generators/migration.rb | 2 +- railties/test/generators/model_generator_test.rb | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/railties/lib/rails/generators/migration.rb b/railties/lib/rails/generators/migration.rb index 8d98909055..0c5c4f6e09 100644 --- a/railties/lib/rails/generators/migration.rb +++ b/railties/lib/rails/generators/migration.rb @@ -52,7 +52,7 @@ module Rails destination = self.class.migration_exists?(migration_dir, @migration_file_name) - if behavior == :invoke + if !(destination && options[:skip]) && behavior == :invoke if destination && options.force? remove_file(destination) elsif destination diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index 8a0f560bc8..552b7eb30a 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -147,10 +147,22 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end - def test_migration_already_exists_error_message + def test_migration_is_skipped_with_skip_option run_generator - error = capture(:stderr){ run_generator ["Account"], :behavior => :skip } - assert_match /Another migration is already named create_accounts/, error + output = run_generator ["Account", "--skip"] + assert_match %r{skip\s+db/migrate/\d+_create_accounts.rb}, output + end + + def test_migration_is_ignored_as_identical_with_skip_option + run_generator ["Account"] + output = run_generator ["Account", "--skip"] + assert_match %r{identical\s+db/migrate/\d+_create_accounts.rb}, output + end + + def test_migration_is_skipped_on_skip_behavior + run_generator + output = run_generator ["Account"], :behavior => :skip + assert_match %r{skip\s+db/migrate/\d+_create_accounts.rb}, output end def test_migration_error_is_not_shown_on_revoke -- cgit v1.2.3 From 2650742bd02e108bc4ccdc59efa54b4916e3a443 Mon Sep 17 00:00:00 2001 From: Samuel Kadolph Date: Thu, 9 Dec 2010 13:30:02 -0500 Subject: Add support for namespaced validators Includes test and documentation for new feature Signed-off-by: Santiago Pastorino --- activemodel/lib/active_model/validations/validates.rb | 8 +++++++- activemodel/test/cases/validations/validates_test.rb | 8 ++++++++ activemodel/test/validators/namespace/email_validator.rb | 6 ++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100755 activemodel/test/validators/namespace/email_validator.rb diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 77c5073c6e..0132f68282 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -55,6 +55,10 @@ module ActiveModel # validates :name, :title => true # end # + # Additionally validator classes may be in another namespace and still used within any class. + # + # validates :name, :'file/title' => true + # # The validators hash can also handle regular expressions, ranges, # arrays and strings in shortcut form, e.g. # @@ -86,8 +90,10 @@ module ActiveModel defaults.merge!(:attributes => attributes) validations.each do |key, options| + key = "#{key.to_s.camelize}Validator" + begin - validator = const_get("#{key.to_s.camelize}Validator") + validator = key.include?('::') ? key.constantize : const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb index 666c48c8a0..3a9900939e 100644 --- a/activemodel/test/cases/validations/validates_test.rb +++ b/activemodel/test/cases/validations/validates_test.rb @@ -3,6 +3,7 @@ require 'cases/helper' require 'models/person' require 'models/person_with_validator' require 'validators/email_validator' +require 'validators/namespace/email_validator' class ValidatesTest < ActiveModel::TestCase setup :reset_callbacks @@ -34,6 +35,13 @@ class ValidatesTest < ActiveModel::TestCase assert_equal ['is not an email'], person.errors[:karma] end + def test_validates_with_namespaced_validator_class + Person.validates :karma, :'namespace/email' => true + person = Person.new + person.valid? + assert_equal ['is not an email'], person.errors[:karma] + end + def test_validates_with_if_as_local_conditions Person.validates :karma, :presence => true, :email => { :unless => :condition_is_true } person = Person.new diff --git a/activemodel/test/validators/namespace/email_validator.rb b/activemodel/test/validators/namespace/email_validator.rb new file mode 100755 index 0000000000..57e2793ce2 --- /dev/null +++ b/activemodel/test/validators/namespace/email_validator.rb @@ -0,0 +1,6 @@ +require 'validators/email_validator' + +module Namespace + class EmailValidator < ::EmailValidator + end +end -- cgit v1.2.3 From 32a2bf8d4e170ce68f895c007da852211892ba5e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 Dec 2010 16:40:05 -0200 Subject: This is not an executable file --- activemodel/test/validators/namespace/email_validator.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 activemodel/test/validators/namespace/email_validator.rb diff --git a/activemodel/test/validators/namespace/email_validator.rb b/activemodel/test/validators/namespace/email_validator.rb old mode 100755 new mode 100644 -- cgit v1.2.3 From 658bb4fa25db0b3f61bfb64028274f2365cad506 Mon Sep 17 00:00:00 2001 From: Chiel Wester Date: Mon, 13 Dec 2010 15:06:23 +0100 Subject: Only call save on belongs_to associations if the record has changed or any nested associations have changed (resolves #3353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activerecord/lib/active_record/autosave_association.rb | 2 +- activerecord/test/cases/autosave_association_test.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index c3dda29d03..4a18719551 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -363,7 +363,7 @@ module ActiveRecord if autosave && association.marked_for_destruction? association.destroy elsif autosave != false - saved = association.save(:validate => !autosave) if association.new_record? || autosave + saved = association.save(:validate => !autosave) if association.new_record? || (autosave && association.changed_for_autosave?) if association.updated? association_id = association.send(reflection.options[:primary_key] || :id) diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index fbf7121468..27aee400f9 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -667,10 +667,21 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end end + @ship.pirate.catchphrase = "Changed Catchphrase" + assert_raise(RuntimeError) { assert !@ship.save } assert_not_nil @ship.reload.pirate end + def test_should_save_changed_child_objects_if_parent_is_saved + @pirate = @ship.create_pirate(:catchphrase => "Don' botharrr talkin' like one, savvy?") + @parrot = @pirate.parrots.create!(:name => 'Posideons Killer') + @parrot.name = "NewName" + @ship.save + + assert_equal 'NewName', @parrot.reload.name + end + # has_many & has_and_belongs_to %w{ parrots birds }.each do |association_name| define_method("test_should_destroy_#{association_name}_as_part_of_the_save_transaction_if_they_were_marked_for_destroyal") do -- cgit v1.2.3 From 6ed6e4f9df7c08cbf053501346beb4b0fb42b348 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 13 Dec 2010 11:39:31 -0800 Subject: persisted? should be able to return a truthy object --- activerecord/test/cases/transactions_test.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index b0ccd71836..110a18772f 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -370,23 +370,23 @@ class TransactionTest < ActiveRecord::TestCase assert topic_2.save @first.save @second.destroy - assert_equal true, topic_1.persisted? + assert topic_1.persisted?, 'persisted' assert_not_nil topic_1.id - assert_equal true, topic_2.persisted? + assert topic_2.persisted?, 'persisted' assert_not_nil topic_2.id - assert_equal true, @first.persisted? + assert @first.persisted?, 'persisted' assert_not_nil @first.id - assert_equal true, @second.destroyed? + assert @second.destroyed?, 'destroyed' raise ActiveRecord::Rollback end - assert_equal false, topic_1.persisted? + assert !topic_1.persisted?, 'not persisted' assert_nil topic_1.id - assert_equal false, topic_2.persisted? + assert !topic_2.persisted?, 'not persisted' assert_nil topic_2.id - assert_equal true, @first.persisted? + assert @first.persisted?, 'persisted' assert_not_nil @first.id - assert_equal false, @second.destroyed? + assert !@second.destroyed?, 'not destroyed' end if current_adapter?(:PostgreSQLAdapter) && defined?(PGconn::PQTRANS_IDLE) -- cgit v1.2.3 From 79e6c7d2301d452c721d0b806071b0ebe2255eca Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 13 Dec 2010 13:21:18 -0800 Subject: stop delegating inserts to ARel, use the INSERT SQL ourselves --- activerecord/lib/active_record/relation.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3009bb70c1..7ecba1c43a 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -11,7 +11,6 @@ module ActiveRecord include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a - delegate :insert, :to => :arel attr_reader :table, :klass, :loaded attr_accessor :extensions @@ -28,6 +27,19 @@ module ActiveRecord @extensions = [] end + def insert(values) + im = arel.compile_insert values + im.into @table + primary_key_name = @klass.primary_key + primary_key_value = Hash === values ? values[primary_key_name] : nil + + @klass.connection.insert( + im.to_sql, + 'SQL', + primary_key_name, + primary_key_value) + end + def new(*args, &block) scoping { @klass.new(*args, &block) } end -- cgit v1.2.3 From 34d1e5d04d2e2583bf28fc2365f43d5917e2c648 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 13 Dec 2010 01:28:27 +0100 Subject: Fix indentation and newlines in generated engine --- railties/lib/rails/generators/named_base.rb | 2 +- .../rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index e0dde4360f..44a2639488 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -42,7 +42,7 @@ module Rails end def wrap_with_namespace(content) - content = indent(content) + content = indent(content).chomp "module #{namespace.name}\n#{content}\nend\n" end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb index 9600ee0c3f..aa8ea77bae 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb @@ -1,7 +1,7 @@ module <%= camelized %> class Engine < Rails::Engine <% if mountable? -%> - isolate_namespace <%= camelized %> + isolate_namespace <%= camelized %> <% end -%> end end -- cgit v1.2.3 From df20c9f1a9b1eed52390cb983e241206961beda0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 13 Dec 2010 13:49:39 -0800 Subject: fixing whitespace errors --- .../test/cases/associations/inner_join_association_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 780eabc443..da2a81e98a 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -65,21 +65,21 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase authors_with_welcoming_post_titles = Author.calculate(:count, 'authors.id', :joins => :posts, :distinct => true, :conditions => "posts.title like 'Welcome%'") assert_equal real_count, authors_with_welcoming_post_titles, "inner join and conditions should have only returned authors posting titles starting with 'Welcome'" end - + def test_find_with_sti_join scope = Post.joins(:special_comments).where(:id => posts(:sti_comments).id) - + # The join should match SpecialComment and its subclasses only assert scope.where("comments.type" => "Comment").empty? assert !scope.where("comments.type" => "SpecialComment").empty? assert !scope.where("comments.type" => "SubSpecialComment").empty? end - + def test_find_with_conditions_on_reflection assert !posts(:welcome).comments.empty? assert Post.joins(:nonexistant_comments).where(:id => posts(:welcome).id).empty? # [sic!] end - + def test_find_with_conditions_on_through_reflection assert !posts(:welcome).tags.empty? assert Post.joins(:misc_tags).where(:id => posts(:welcome).id).empty? -- cgit v1.2.3 From 90d9aa3b452354cddb2be5ce5ca2f6d0d0112431 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 11:25:47 -0800 Subject: taking advantage of the JoinSource node in the SQL AST --- .../associations/class_methods/join_dependency.rb | 20 ++++++------------- .../join_dependency/join_association.rb | 1 - .../lib/active_record/relation/finder_methods.rb | 2 +- .../lib/active_record/relation/query_methods.rb | 23 +++++++--------------- 4 files changed, 14 insertions(+), 32 deletions(-) diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb index 5a0ff942ca..a74d0a4ca8 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency.rb @@ -47,24 +47,16 @@ module ActiveRecord end def count_aliases_from_table_joins(name) - return 0 if !@table_joins || Arel::Table === @table_joins + return 0 if Arel::Table === @table_joins # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase quoted_name = active_record.connection.quote_table_name(name).downcase - @table_joins.grep(Arel::Nodes::Join).map { |join| - right = join.right - case right - when Arel::Table - right.name.downcase == name ? 1 : 0 - when String - # Table names + table aliases - right.downcase.scan( - /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ - ).size - else - 0 - end + @table_joins.map { |join| + # Table names + table aliases + join.left.downcase.scan( + /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/ + ).size }.sum end diff --git a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb index c552603097..694778008b 100644 --- a/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb +++ b/activerecord/lib/active_record/associations/class_methods/join_dependency/join_association.rb @@ -138,7 +138,6 @@ module ActiveRecord ands = relation.create_and(conditions) join = relation.create_join( - relation.froms.first, target_table, relation.create_on(ands), join_type) diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 906ad7699c..8bc28c06cb 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -187,7 +187,7 @@ module ActiveRecord def find_with_associations including = (@eager_load_values + @includes_values).uniq - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, nil) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, []) rows = construct_relation_for_association_find(join_dependency).to_a join_dependency.instantiate(rows) rescue ThrowResult diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 51a39be065..67a94cec85 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -191,27 +191,19 @@ module ActiveRecord def custom_join_ast(table, joins) joins = joins.reject { |join| join.blank? } - return if joins.empty? + return [] if joins.empty? @implicit_readonly = true - joins.map! do |join| + joins.map do |join| case join when Array join = Arel.sql(join.join(' ')) if array_of_strings?(join) when String join = Arel.sql(join) end - join + table.create_string_join(join) end - - head = table.create_string_join(table, joins.shift) - - joins.inject(head) do |ast, join| - ast.right = table.create_string_join(ast.right, join) - end - - head end def collapse_wheres(arel, wheres) @@ -256,9 +248,9 @@ module ActiveRecord stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) non_association_joins = (joins - association_joins - stashed_association_joins) - join_ast = custom_join_ast(manager.froms.first, non_association_joins) + join_list = custom_join_ast(manager, non_association_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_ast) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) join_dependency.graft(*stashed_association_joins) @@ -269,10 +261,9 @@ module ActiveRecord association.join_to(manager) end - return manager unless join_ast + return manager unless join_list - join_ast.left = manager.froms.first - manager.from join_ast + join_list.each { |j| manager.from j } manager end -- cgit v1.2.3 From fdabb8fe176921d65b0e056d6f41ed9a63650945 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 12:34:04 -0800 Subject: bucketing based on join type --- .../lib/active_record/relation/query_methods.rb | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 67a94cec85..ef14f48a8f 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -239,16 +239,25 @@ module ActiveRecord end def build_joins(manager, joins) - joins = joins.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq - - association_joins = joins.find_all do |join| - [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join) + buckets = joins.group_by do |join| + case join + when String + 'string_join' + when Hash, Symbol, Array + 'association_join' + when ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation + 'stashed_join' + else + raise 'unknown class: %s' % join.class.name + end end - stashed_association_joins = joins.grep(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation) - - non_association_joins = (joins - association_joins - stashed_association_joins) - join_list = custom_join_ast(manager, non_association_joins) + association_joins = buckets['association_join'] || [] + stashed_association_joins = buckets['stashed_join'] || [] + string_joins = (buckets['string_join'] || []).map { |x| + x.strip + }.uniq + join_list = custom_join_ast(manager, string_joins) join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) -- cgit v1.2.3 From 6212ecaa0be6c0f035d9be26e8693bd1f09fdfb6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 14:49:33 -0800 Subject: just copy the joins to the list --- .../lib/active_record/associations/has_many_through_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index d0c8af1801..6ad51e2fb4 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -54,7 +54,7 @@ module ActiveRecord end def construct_find_options!(options) - options[:joins] = construct_joins(options[:joins]) + options[:joins] = [construct_joins] + Array.wrap(options[:joins]) options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? && @reflection.source_reflection.options[:include] end -- cgit v1.2.3 From 2e7da54f770d1e076005c7670ab8d99431888faa Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 14:57:03 -0800 Subject: supporting arel AST nodes when building join statements --- .../associations/through_association_scope.rb | 32 ++++++++++++---------- .../lib/active_record/relation/query_methods.rb | 18 ++++++++++-- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index acddfda924..48386ee124 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -55,33 +55,35 @@ module ActiveRecord end def construct_joins(custom_joins = nil) - polymorphic_join = nil + right = @reflection.through_reflection.klass.arel_table + left = @reflection.klass.arel_table + + conditions = [] + if @reflection.source_reflection.macro == :belongs_to reflection_primary_key = @reflection.klass.primary_key source_primary_key = @reflection.source_reflection.primary_key_name if @reflection.options[:source_type] - polymorphic_join = "AND %s.%s = %s" % [ - @reflection.through_reflection.quoted_table_name, "#{@reflection.source_reflection.options[:foreign_type]}", - @owner.class.quote_value(@reflection.options[:source_type]) - ] + column = @reflection.source_reflection.options[:foreign_type] + conditions << + right[column].eq(@reflection.options[:source_type]) end else reflection_primary_key = @reflection.source_reflection.primary_key_name source_primary_key = @reflection.through_reflection.klass.primary_key if @reflection.source_reflection.options[:as] - polymorphic_join = "AND %s.%s = %s" % [ - @reflection.quoted_table_name, "#{@reflection.source_reflection.options[:as]}_type", - @owner.class.quote_value(@reflection.through_reflection.klass.name) - ] + column = "#{@reflection.source_reflection.options[:as]}_type" + conditions << + left[column].eq(@reflection.through_reflection.klass.name) end end - "INNER JOIN %s ON %s.%s = %s.%s %s #{@reflection.options[:joins]} #{custom_joins}" % [ - @reflection.through_reflection.quoted_table_name, - @reflection.quoted_table_name, reflection_primary_key, - @reflection.through_reflection.quoted_table_name, source_primary_key, - polymorphic_join - ] + conditions << + left[reflection_primary_key].eq(right[source_primary_key]) + + right.create_join( + right, + right.create_on(right.create_and(conditions))) end # Construct attributes for associate pointing to owner. diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index ef14f48a8f..8e50f4a9bc 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -247,6 +247,8 @@ module ActiveRecord 'association_join' when ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation 'stashed_join' + when Arel::Nodes::Join + 'join_node' else raise 'unknown class: %s' % join.class.name end @@ -254,12 +256,22 @@ module ActiveRecord association_joins = buckets['association_join'] || [] stashed_association_joins = buckets['stashed_join'] || [] + join_nodes = buckets['join_node'] || [] string_joins = (buckets['string_join'] || []).map { |x| x.strip }.uniq + join_list = custom_join_ast(manager, string_joins) - join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, join_list) + join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new( + @klass, + association_joins, + join_list + ) + + join_nodes.each do |join| + join_dependency.table_aliases[join.left.name.downcase] = 1 + end join_dependency.graft(*stashed_association_joins) @@ -270,9 +282,9 @@ module ActiveRecord association.join_to(manager) end - return manager unless join_list + manager.join_sources.concat join_nodes + manager.join_sources.concat join_list - join_list.each { |j| manager.from j } manager end -- cgit v1.2.3 From 7af9ec8a99bbc044af1f08200b4aa350ac64a53d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:03:06 -0800 Subject: construct_joins no longer needs an argument --- .../lib/active_record/associations/through_association_scope.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 48386ee124..f6b242168c 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -54,7 +54,7 @@ module ActiveRecord custom_select || @reflection.options[:select] || "#{distinct}#{@reflection.quoted_table_name}.*" end - def construct_joins(custom_joins = nil) + def construct_joins right = @reflection.through_reflection.klass.arel_table left = @reflection.klass.arel_table -- cgit v1.2.3 From 820582883a301ad813534492f8f3223a582824f1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:24:25 -0800 Subject: build SQL AST nodes rather than generate strings --- .../associations/through_association_scope.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index f6b242168c..8d701248af 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -23,25 +23,23 @@ module ActiveRecord # Build SQL conditions from attributes, qualified by table name. def construct_conditions - table_name = @reflection.through_reflection.quoted_table_name + table = @reflection.through_reflection.klass.arel_table conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value| - "#{table_name}.#{attr} = #{value}" + table[attr].eq(value) end - conditions << sql_conditions if sql_conditions - "(" + conditions.join(') AND (') + ")" + conditions << Arel.sql(sql_conditions) if sql_conditions + table.create_and(conditions) end # Associate attributes pointing to owner, quoted. def construct_quoted_owner_attributes(reflection) if as = reflection.options[:as] - { "#{as}_id" => owner_quoted_id, - "#{as}_type" => reflection.klass.quote_value( - @owner.class.base_class.name.to_s, - reflection.klass.columns_hash["#{as}_type"]) } + { "#{as}_id" => @owner.id, + "#{as}_type" => @owner.class.base_class.name } elsif reflection.macro == :belongs_to - { reflection.klass.primary_key => @owner.class.quote_value(@owner[reflection.primary_key_name]) } + { reflection.klass.primary_key => @owner[reflection.primary_key_name] } else - { reflection.primary_key_name => owner_quoted_id } + { reflection.primary_key_name => @owner.id } end end -- cgit v1.2.3 From f2234a5dd3a1d891e585a703f1a432153e4d2c18 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 14 Dec 2010 15:27:06 -0800 Subject: class names are already strings, so we do not need to call to_s on the strings that are already strings --- .../lib/active_record/associations/through_association_scope.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 8d701248af..6b7faa9fc3 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -88,7 +88,7 @@ module ActiveRecord def construct_owner_attributes(reflection) if as = reflection.options[:as] { "#{as}_id" => @owner.id, - "#{as}_type" => @owner.class.base_class.name.to_s } + "#{as}_type" => @owner.class.base_class.name } else { reflection.primary_key_name => @owner.id } end @@ -102,7 +102,7 @@ module ActiveRecord join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id) if @reflection.options[:source_type] - join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s) + join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name) end if @reflection.through_reflection.options[:conditions].is_a?(Hash) -- cgit v1.2.3 From 00c893d3b86be3a141c21ed065e085adbb26062a Mon Sep 17 00:00:00 2001 From: Joe Hannon Date: Sun, 2 May 2010 16:26:02 -0700 Subject: add test which fails for has_many through self join [#4361 state:open] --- .../test/cases/associations/has_many_through_associations_test.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 52432b0428..fe60e676d6 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -388,6 +388,13 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase ].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) } end + def test_has_many_association_through_a_has_many_association_to_self + sarah = Person.create!(:first_name => 'Sarah', :primary_contact_id => people(:susan).id, :gender => 'F', :number1_fan_id => 1) + john = Person.create!(:first_name => 'John', :primary_contact_id => sarah.id, :gender => 'M', :number1_fan_id => 1) + assert_equal sarah.agents, [john] + assert_equal people(:susan).agents_of_agents, [john] + end + def test_collection_singular_ids_getter_with_string_primary_keys book = books(:awdr) assert_equal 2, book.subscriber_ids.size -- cgit v1.2.3 From c81af00a7ab64ec1159e8b319f8498ea5b9037c7 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 3 May 2010 20:47:42 -0400 Subject: Fix hm:t to self table aliasing in construct_scope --- .../active_record/associations/through_association_scope.rb | 12 ++++++++++-- .../cases/associations/has_many_through_associations_test.rb | 2 +- activerecord/test/models/person.rb | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index 6b7faa9fc3..a55bf6323e 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -21,9 +21,17 @@ module ActiveRecord construct_owner_attributes(@reflection) end + def aliased_through_table + name = @reflection.through_reflection.table_name + + @reflection.table_name == name ? + @reflection.through_reflection.klass.arel_table.alias(name + "_join") : + @reflection.through_reflection.klass.arel_table + end + # Build SQL conditions from attributes, qualified by table name. def construct_conditions - table = @reflection.through_reflection.klass.arel_table + table = aliased_through_table conditions = construct_quoted_owner_attributes(@reflection.through_reflection).map do |attr, value| table[attr].eq(value) end @@ -53,7 +61,7 @@ module ActiveRecord end def construct_joins - right = @reflection.through_reflection.klass.arel_table + right = aliased_through_table left = @reflection.klass.arel_table conditions = [] diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index fe60e676d6..34ae297275 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -392,7 +392,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase sarah = Person.create!(:first_name => 'Sarah', :primary_contact_id => people(:susan).id, :gender => 'F', :number1_fan_id => 1) john = Person.create!(:first_name => 'John', :primary_contact_id => sarah.id, :gender => 'M', :number1_fan_id => 1) assert_equal sarah.agents, [john] - assert_equal people(:susan).agents_of_agents, [john] + assert_equal people(:susan).agents.map(&:agents).flatten, people(:susan).agents_of_agents end def test_collection_singular_ids_getter_with_string_primary_keys diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index 951ec93c53..bee89de042 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -12,6 +12,7 @@ class Person < ActiveRecord::Base belongs_to :primary_contact, :class_name => 'Person' has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id' + has_many :agents_of_agents, :through => :agents, :source => :agents belongs_to :number1_fan, :class_name => 'Person' scope :males, :conditions => { :gender => 'M' } -- cgit v1.2.3 From 5e3b853aee86b74e68c9c3f95201c54af5502d2f Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 09:09:29 +0100 Subject: Should be isolated engine instead of namespaced engine --- railties/lib/rails/engine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index cda0e0a135..1d81e08cd3 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -207,7 +207,7 @@ module Rails # end # end # - # == Namespaced Engine + # == Isolated Engine # # Normally when you create controllers, helpers and models inside engine, they are treated # as they were created inside the application. This means all applications helpers and named routes -- cgit v1.2.3 From 0e5ee9af48f11201a3b06fb3f5a50144224ec9e8 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 09:01:18 +0100 Subject: Set proper engine's asset directories when assets are served from engine. When using stylesheet_link_tag(:all) or javascript_include_tag(:all), assets directories are searched for css or js files. When config.serve_static_assets is set to true, those files can be served directly from engine's directories. That's why assets paths should be set individually for controllers inside engine if we want to serve static assets with ActionDispatch::Static --- actionpack/lib/action_controller/railties/paths.rb | 8 +++ railties/test/railties/engine_test.rb | 64 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/actionpack/lib/action_controller/railties/paths.rb b/actionpack/lib/action_controller/railties/paths.rb index 699c44c62c..dce3c2fe88 100644 --- a/actionpack/lib/action_controller/railties/paths.rb +++ b/actionpack/lib/action_controller/railties/paths.rb @@ -16,6 +16,14 @@ module ActionController if klass.superclass == ActionController::Base && ActionController::Base.include_all_helpers klass.helper :all end + + if app.config.serve_static_assets && namespace + paths = namespace._railtie.config.paths + + klass.config.assets_dir = paths["public"].first + klass.config.javascripts_dir = paths["public/javascripts"].first + klass.config.stylesheets_dir = paths["public/stylesheets"].first + end end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 05bd0c36cd..6b64a19741 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -721,5 +721,69 @@ module RailtiesTest engine_path = File.join(@plugin.path, '..', engine_dir) assert_equal Bukkits::Engine.instance, Rails::Engine.find(engine_path) end + + test "ensure that engine properly sets assets directories" do + add_to_config("config.action_dispatch.show_exceptions = false") + add_to_config("config.serve_static_assets = true") + + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace Bukkits + end + end + RUBY + + @plugin.write "public/stylesheets/foo.css", "" + @plugin.write "public/javascripts/foo.js", "" + + @plugin.write "app/views/layouts/bukkits/application.html.erb", <<-RUBY + <%= stylesheet_link_tag :all %> + <%= javascript_include_tag :all %> + <%= yield %> + RUBY + + @plugin.write "app/controllers/bukkits/home_controller.rb", <<-RUBY + module Bukkits + class HomeController < ActionController::Base + def index + render :text => "Good morning!", :layout => "bukkits/application" + end + end + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/home" => "home#index" + end + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + mount Bukkits::Engine => "/bukkits" + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + + boot_rails + + require "#{rails_root}/config/environment" + + assert_equal File.join(@plugin.path, "public"), Bukkits::HomeController.assets_dir + assert_equal File.join(@plugin.path, "public/stylesheets"), Bukkits::HomeController.stylesheets_dir + assert_equal File.join(@plugin.path, "public/javascripts"), Bukkits::HomeController.javascripts_dir + + assert_equal File.join(app_path, "public"), ActionController::Base.assets_dir + assert_equal File.join(app_path, "public/stylesheets"), ActionController::Base.stylesheets_dir + assert_equal File.join(app_path, "public/javascripts"), ActionController::Base.javascripts_dir + + get "/bukkits/home" + + assert_match %r{bukkits/stylesheets/foo.css}, last_response.body + assert_match %r{bukkits/javascripts/foo.js}, last_response.body + end end end -- cgit v1.2.3 From 5d63a36ae8c2a839d0a197b10250184a035064e7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 12:20:20 +0100 Subject: Generate javascripts in engine with --mountable option --- railties/lib/rails/generators/app_base.rb | 6 ++++ .../rails/generators/rails/app/app_generator.rb | 5 ---- .../rails/plugin_new/plugin_new_generator.rb | 35 ++++++++++++++++++++++ .../test/generators/plugin_new_generator_test.rb | 29 ++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 2d0c10efca..7766050632 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -171,6 +171,12 @@ gem 'rails', '#{Rails::VERSION::STRING}' def dev_or_edge? options.dev? || options.edge? end + + def empty_directory_with_gitkeep(destination, config = {}) + empty_directory(destination, config) + create_file("#{destination}/.gitkeep") unless options[:skip_git] + end + end end end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ef1eb8d237..f833b5d041 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -317,11 +317,6 @@ module Rails ].find { |f| File.exist?(f) } unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ end - def empty_directory_with_gitkeep(destination, config = {}) - empty_directory(destination, config) - create_file("#{destination}/.gitkeep") unless options[:skip_git] - end - def get_builder_class defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder end diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 9c54b98238..3cd4fa4ba1 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -88,6 +88,29 @@ task :default => :test end end + def stylesheets + empty_directory_with_gitkeep "public/stylesheets" if options[:mountable] + end + + def javascripts + return unless options[:mountable] + + empty_directory "#{app_templates_dir}/public/javascripts" + + unless options[:skip_javascript] + copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}.js", "public/javascripts/#{options[:javascript]}.js" + copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js" + + if options[:prototype] + copy_file "#{app_templates_dir}/public/javascripts/controls.js", "public/javascripts/controls.js" + copy_file "#{app_templates_dir}/public/javascripts/dragdrop.js", "public/javascripts/dragdrop.js" + copy_file "#{app_templates_dir}/public/javascripts/effects.js", "public/javascripts/effects.js" + end + end + + copy_file "#{app_templates_dir}/public/javascripts/application.js", "public/javascripts/application.js" + end + def script(force = false) directory "script", :force => force do |content| "#{shebang}\n" + content @@ -143,6 +166,14 @@ task :default => :test build(:lib) end + def create_public_stylesheets_files + build(:stylesheets) + end + + def create_javascript_files + build(:javascripts) + end + def create_script_files build(:script) end @@ -163,6 +194,10 @@ task :default => :test public_task :apply_rails_template, :bundle_if_dev_or_edge protected + def app_templates_dir + "../../app/templates" + end + def create_dummy_app(path = nil) dummy_path(path) if path diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 0d24821ff6..e146cb2bb3 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -91,6 +91,35 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "test/dummy/config/database.yml", /postgres/ end + def test_skipping_javascripts_without_mountable_option + run_generator + assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/rails.js" + assert_no_file "public/javascripts/controls.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/application.js" + end + + def test_javascripts_generation + run_generator [destination_root, "--mountable"] + assert_file "public/javascripts/rails.js" + assert_file "public/javascripts/prototype.js" + assert_file "public/javascripts/controls.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/application.js" + end + + def test_skip_javascripts + run_generator [destination_root, "--skip-javascript", "--mountable"] + assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/rails.js" + assert_no_file "public/javascripts/controls.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/dragdrop.js" + end + def test_ensure_that_javascript_option_is_passed_to_app_generator run_generator [destination_root, "--javascript", "jquery"] assert_file "test/dummy/public/javascripts/jquery.js" -- cgit v1.2.3 From 779a60dee553bda9a5238ac658d68f5022cf9810 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 12:56:29 +0100 Subject: Fix generation of prototype files, it should work with --javascript prototype, not --prototype --- railties/lib/rails/generators/rails/app/app_generator.rb | 2 +- railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb | 2 +- railties/test/generators/app_generator_test.rb | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index f833b5d041..d25372ea8e 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -109,7 +109,7 @@ module Rails copy_file "public/javascripts/#{@options[:javascript]}.js" copy_file "public/javascripts/#{@options[:javascript]}_ujs.js", "public/javascripts/rails.js" - if options[:prototype] + if options[:javascript] == "prototype" copy_file "public/javascripts/controls.js" copy_file "public/javascripts/dragdrop.js" copy_file "public/javascripts/effects.js" diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 3cd4fa4ba1..47a84e228c 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -101,7 +101,7 @@ task :default => :test copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}.js", "public/javascripts/#{options[:javascript]}.js" copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js" - if options[:prototype] + if options[:javascript] == "prototype" copy_file "#{app_templates_dir}/public/javascripts/controls.js", "public/javascripts/controls.js" copy_file "#{app_templates_dir}/public/javascripts/dragdrop.js", "public/javascripts/dragdrop.js" copy_file "#{app_templates_dir}/public/javascripts/effects.js", "public/javascripts/effects.js" diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 7faa674a81..02c49ab241 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -135,6 +135,9 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "public/javascripts/application.js" assert_file "public/javascripts/prototype.js" assert_file "public/javascripts/rails.js" + assert_file "public/javascripts/controls.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/dragdrop.js" assert_file "test" end -- cgit v1.2.3 From 232e37952d90a115273c798b8208c1c563a2c9d4 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 15 Dec 2010 12:20:48 +0100 Subject: Generate default layout in engine with --mountable option --- railties/lib/rails/generators/rails/app/app_generator.rb | 1 + .../rails/app/templates/app/views/layouts/application.html.erb.tt | 2 +- .../lib/rails/generators/rails/plugin_new/plugin_new_generator.rb | 6 +++++- railties/test/generators/plugin_new_generator_test.rb | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d25372ea8e..d842797883 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -284,6 +284,7 @@ module Rails def app_const_base @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, '_').squeeze('_').camelize end + alias :camelized :app_const_base def app_const @app_const ||= "#{app_const_base}::Application" diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index 1de78eecae..6d56c331c1 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -1,7 +1,7 @@ - <%= app_const_base %> + <%= camelized %> <%%= stylesheet_link_tag :all %> <%%= javascript_include_tag :defaults %> <%%= csrf_meta_tags %> diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 47a84e228c..9461589ff5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -8,7 +8,11 @@ module Rails end def app - directory "app" if options[:mountable] + if options[:mountable] + directory "app" + template "#{app_templates_dir}/app/views/layouts/application.html.erb.tt", + "app/views/layouts/#{name}/application.html.erb" + end end def readme diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index e146cb2bb3..2a9e8046b8 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -166,6 +166,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/ assert_file "app/controllers/bukkits/application_controller.rb", /module Bukkits\n class ApplicationController < ActionController::Base/ assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/ + assert_file "app/views/layouts/bukkits/application.html.erb", /Bukkits<\/title>/ end def test_passing_dummy_path_as_a_parameter -- cgit v1.2.3 From 2dafb14c287af2970ceb45ded9ab4e5ce109738f Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki <drogus@gmail.com> Date: Wed, 15 Dec 2010 12:21:46 +0100 Subject: Kill whitespace! --- railties/lib/rails/generators/rails/app/app_generator.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index d842797883..94af9fe1e9 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -104,18 +104,18 @@ module Rails def javascripts empty_directory "public/javascripts" - + unless options[:skip_javascript] copy_file "public/javascripts/#{@options[:javascript]}.js" copy_file "public/javascripts/#{@options[:javascript]}_ujs.js", "public/javascripts/rails.js" - + if options[:javascript] == "prototype" copy_file "public/javascripts/controls.js" copy_file "public/javascripts/dragdrop.js" copy_file "public/javascripts/effects.js" end end - + copy_file "public/javascripts/application.js" end -- cgit v1.2.3 From 17afec0ae3fe9d8895a7e030f6bfb8443ae83be1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki <drogus@gmail.com> Date: Wed, 15 Dec 2010 13:08:49 +0100 Subject: AppGenerator: use options instead of @options --- railties/lib/rails/generators/rails/app/app_generator.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 94af9fe1e9..3f6ff35a86 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -63,7 +63,7 @@ module Rails end def database_yml - template "config/databases/#{@options[:database]}.yml", "config/database.yml" + template "config/databases/#{options[:database]}.yml", "config/database.yml" end def db @@ -106,8 +106,8 @@ module Rails empty_directory "public/javascripts" unless options[:skip_javascript] - copy_file "public/javascripts/#{@options[:javascript]}.js" - copy_file "public/javascripts/#{@options[:javascript]}_ujs.js", "public/javascripts/rails.js" + copy_file "public/javascripts/#{options[:javascript]}.js" + copy_file "public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js" if options[:javascript] == "prototype" copy_file "public/javascripts/controls.js" -- cgit v1.2.3 From 439c23dce33148064c258eaf6e79f9d4563c88a4 Mon Sep 17 00:00:00 2001 From: brainopia <ravwar@gmail.com> Date: Thu, 9 Dec 2010 18:38:52 +0300 Subject: Fix edge cases for domain :all option on cookie store Dont set explicit domain for cookies if host is not a domain name [#6002 state:committed] Signed-off-by: Santiago Pastorino <santiago@wyeworks.com> --- .../lib/action_dispatch/middleware/cookies.rb | 7 +++++-- actionpack/test/dispatch/cookies_test.rb | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index b0a4e3d949..f369d2d3c2 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -131,8 +131,11 @@ module ActionDispatch options[:path] ||= "/" if options[:domain] == :all - @host =~ DOMAIN_REGEXP - options[:domain] = ".#{$1}.#{$2}" + # if host is not ip and matches domain regexp + # (ip confirms to domain regexp so we explicitly check for ip) + options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ DOMAIN_REGEXP) + ".#{$1}.#{$2}" + end end end diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 5ec7f12cc1..e2040401c7 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -295,6 +295,27 @@ class CookiesTest < ActionController::TestCase assert_cookie_header "user_name=rizwanreza; domain=.nextangle.local; path=/" end + def test_cookie_with_all_domain_option_using_localhost + @request.host = "localhost" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + + def test_cookie_with_all_domain_option_using_ipv4_address + @request.host = "192.168.1.1" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + + def test_cookie_with_all_domain_option_using_ipv6_address + @request.host = "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + get :set_cookie_with_domain + assert_response :success + assert_cookie_header "user_name=rizwanreza; path=/" + end + def test_deleting_cookie_with_all_domain_option get :delete_cookie_with_domain assert_response :success -- cgit v1.2.3 From 16e93f2c3c3ca37d2bae9801b680b05f75c48c18 Mon Sep 17 00:00:00 2001 From: Jon Leighton <j@jonathanleighton.com> Date: Sun, 12 Dec 2010 16:35:27 +0000 Subject: Respect the default_scope on a join model when reading a through association --- .../active_record/associations/has_many_through_association.rb | 2 +- .../active_record/associations/has_one_through_association.rb | 2 +- .../active_record/associations/through_association_scope.rb | 7 +++++++ .../cases/associations/has_many_through_associations_test.rb | 4 ++++ .../cases/associations/has_one_through_associations_test.rb | 10 +++++++++- activerecord/test/models/author.rb | 4 ++++ activerecord/test/models/contract.rb | 2 +- activerecord/test/models/post.rb | 7 +++++++ 8 files changed, 34 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 6ad51e2fb4..781aa7ef62 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -81,7 +81,7 @@ module ActiveRecord def find_target return [] unless target_reflection_has_associated_record? - with_scope(@scope) { @reflection.klass.find(:all) } + scoped.all end def has_cached_counter? diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index 7f28abf464..e8cf73976b 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -33,7 +33,7 @@ module ActiveRecord private def find_target - with_scope(@scope) { @reflection.klass.find(:first) } + scoped.first end end end diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb index a55bf6323e..2ecd0f054a 100644 --- a/activerecord/lib/active_record/associations/through_association_scope.rb +++ b/activerecord/lib/active_record/associations/through_association_scope.rb @@ -3,6 +3,13 @@ module ActiveRecord module Associations module ThroughAssociationScope + def scoped + with_scope(@scope) do + @reflection.klass.scoped & + @reflection.through_reflection.klass.scoped + end + end + protected def construct_find_scope diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 34ae297275..113d0f6d73 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -462,4 +462,8 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase post.people << people(:michael) assert_equal readers + 1, post.readers.size end + + def test_has_many_through_with_default_scope_on_join_model + assert_equal posts(:welcome).comments, authors(:david).comments_on_first_posts + end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index ac43e571cb..93a4f498d0 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -9,9 +9,13 @@ require 'models/member_detail' require 'models/minivan' require 'models/dashboard' require 'models/speedometer' +require 'models/author' +require 'models/post' +require 'models/comment' class HasOneThroughAssociationsTest < ActiveRecord::TestCase - fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans, :dashboards, :speedometers + fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations, :minivans, + :dashboards, :speedometers, :authors, :posts, :comments def setup @member = members(:groucho) @@ -229,4 +233,8 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase minivan.dashboard end end + + def test_has_one_through_with_default_scope_on_join_model + assert_equal posts(:welcome).comments.first, authors(:david).comment_on_first_posts + end end diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index 34bfd2d881..29ee50e801 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -26,6 +26,10 @@ class Author < ActiveRecord::Base has_many :comments_with_order_and_conditions, :through => :posts, :source => :comments, :order => 'comments.body', :conditions => "comments.body like 'Thank%'" has_many :comments_with_include, :through => :posts, :source => :comments, :include => :post + has_many :first_posts + has_many :comments_on_first_posts, :through => :first_posts, :source => :comments, :order => 'posts.id desc, comments.id asc' + has_one :comment_on_first_posts, :through => :first_posts, :source => :comments, :order => 'posts.id desc, comments.id asc' + has_many :thinking_posts, :class_name => 'Post', :conditions => { :title => 'So I was thinking' }, :dependent => :delete_all has_many :welcome_posts, :class_name => 'Post', :conditions => { :title => 'Welcome to the weblog' } diff --git a/activerecord/test/models/contract.rb b/activerecord/test/models/contract.rb index 606c99cd4e..94fd48e12a 100644 --- a/activerecord/test/models/contract.rb +++ b/activerecord/test/models/contract.rb @@ -1,4 +1,4 @@ class Contract < ActiveRecord::Base belongs_to :company belongs_to :developer -end \ No newline at end of file +end diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 61e782ff14..164b499bf0 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -119,3 +119,10 @@ class PostForAuthor < ActiveRecord::Base cattr_accessor :selected_author default_scope lambda { where(:author_id => PostForAuthor.selected_author) } end + +class FirstPost < ActiveRecord::Base + self.table_name = 'posts' + default_scope where(:id => 1) + has_many :comments, :foreign_key => :post_id + has_one :comment, :foreign_key => :post_id +end -- cgit v1.2.3 From a04e1036691ca98579dd8b8b6cb19ffb23f85c72 Mon Sep 17 00:00:00 2001 From: Jon Leighton <j@jonathanleighton.com> Date: Sun, 12 Dec 2010 17:03:41 +0000 Subject: Verify that creating a has_many through record where there is a default_scope on the join model works correctly (creates the join record with the default scope applied) --- .../cases/associations/has_many_through_associations_test.rb | 7 +++++++ activerecord/test/models/author.rb | 4 ++++ activerecord/test/models/categorization.rb | 11 ++++++++++- activerecord/test/schema/schema.rb | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 113d0f6d73..44ff01ddc0 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -17,6 +17,8 @@ require 'models/developer' require 'models/subscriber' require 'models/book' require 'models/subscription' +require 'models/categorization' +require 'models/category' class HasManyThroughAssociationsTest < ActiveRecord::TestCase fixtures :posts, :readers, :people, :comments, :authors, @@ -466,4 +468,9 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase def test_has_many_through_with_default_scope_on_join_model assert_equal posts(:welcome).comments, authors(:david).comments_on_first_posts end + + def test_create_has_many_through_with_default_scope_on_join_model + category = authors(:david).special_categories.create(:name => "Foo") + assert_equal 1, category.categorizations.where(:special => true).count + end end diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index 29ee50e801..fd6d2b384a 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -77,6 +77,10 @@ class Author < ActiveRecord::Base has_many :categorizations has_many :categories, :through => :categorizations + has_many :special_categorizations + has_many :special_categories, :through => :special_categorizations, :source => :category + has_one :special_category, :through => :special_categorizations, :source => :category + has_many :categories_like_general, :through => :categorizations, :source => :category, :class_name => 'Category', :conditions => { :name => 'General' } has_many :categorized_posts, :through => :categorizations, :source => :post diff --git a/activerecord/test/models/categorization.rb b/activerecord/test/models/categorization.rb index 10594323ff..b3fc29fa15 100644 --- a/activerecord/test/models/categorization.rb +++ b/activerecord/test/models/categorization.rb @@ -2,4 +2,13 @@ class Categorization < ActiveRecord::Base belongs_to :post belongs_to :category belongs_to :author -end \ No newline at end of file +end + +class SpecialCategorization < ActiveRecord::Base + self.table_name = 'categorizations' + + default_scope where(:special => true) + + belongs_to :author + belongs_to :category +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index d4eb56c4d7..177045ac51 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -112,6 +112,7 @@ ActiveRecord::Schema.define do t.column :category_id, :integer t.column :post_id, :integer t.column :author_id, :integer + t.column :special, :boolean end create_table :citations, :force => true do |t| -- cgit v1.2.3 From 5d78b4c6f7829498e5d2a8cd4fceca0e24a3f64e Mon Sep 17 00:00:00 2001 From: Aaron Patterson <aaron.patterson@gmail.com> Date: Wed, 15 Dec 2010 11:12:33 -0800 Subject: make sure that join nodes are uniq --- activerecord/lib/active_record/relation/query_methods.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 8e50f4a9bc..6660df302b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -282,7 +282,7 @@ module ActiveRecord association.join_to(manager) end - manager.join_sources.concat join_nodes + manager.join_sources.concat join_nodes.uniq manager.join_sources.concat join_list manager -- cgit v1.2.3 From 6df88f0d2c5fb65f5b94b6c553b000098b9f2eee Mon Sep 17 00:00:00 2001 From: Pivotal Labs <pivotal@lapidge.flood.pivotallabs.com> Date: Fri, 9 Jan 2009 12:13:17 -0800 Subject: test for eager load of has_one association with condition on the through table --- activerecord/test/cases/associations/eager_test.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index c96ca90750..34a1cdeebe 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -17,18 +17,26 @@ require 'models/subscription' require 'models/book' require 'models/developer' require 'models/project' +require 'models/member' +require 'models/membership' +require 'models/club' class EagerAssociationTest < ActiveRecord::TestCase fixtures :posts, :comments, :authors, :author_addresses, :categories, :categories_posts, :companies, :accounts, :tags, :taggings, :people, :readers, :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books, - :developers, :projects, :developers_projects + :developers, :projects, :developers_projects, :members, :memberships, :clubs def setup # preheat table existence caches Comment.find_by_id(1) end + def test_eager_with_has_one_through_join_model_with_conditions_on_the_through + member = Member.find(members(:some_other_guy).id, :include => :favourite_club) + assert_nil member.favourite_club + end + def test_loading_with_one_association posts = Post.find(:all, :include => :comments) post = posts.find { |p| p.id == 1 } -- cgit v1.2.3