diff options
-rw-r--r-- | actionview/CHANGELOG.md | 6 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/asset_tag_helper.rb | 1 | ||||
-rw-r--r-- | actionview/test/template/asset_tag_helper_test.rb | 2 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb | 12 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb | 43 | ||||
-rw-r--r-- | activerecord/test/cases/migration/foreign_key_test.rb | 21 | ||||
-rw-r--r-- | guides/CHANGELOG.md | 4 | ||||
-rw-r--r-- | guides/source/active_record_validations.md | 5 | ||||
-rw-r--r-- | guides/source/configuring.md | 18 | ||||
-rw-r--r-- | guides/source/debugging_rails_applications.md | 52 | ||||
-rw-r--r-- | guides/source/working_with_javascript_in_rails.md | 28 |
12 files changed, 177 insertions, 19 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 7fc32a3b5c..534124d208 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,9 @@ +* Allow to pass a string value to `size` option in `image_tag` and `video_tag`. + + This makes the behavior more consistent with `width` or `height` options. + + *Mehdi Lahmam* + * Partial template name does no more have to be a valid Ruby identifier. There used to be a naming rule that the partial name should start with diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index b7fdc16a9d..5c28043f8a 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -318,6 +318,7 @@ module ActionView end def extract_dimensions(size) + size = size.to_s if size =~ %r{\A\d+x\d+\z} size.split('x') elsif size =~ %r{\A\d+\z} diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb index dac1c7024d..a15c6fac90 100644 --- a/actionview/test/template/asset_tag_helper_test.rb +++ b/actionview/test/template/asset_tag_helper_test.rb @@ -180,6 +180,7 @@ class AssetTagHelperTest < ActionView::TestCase %(image_tag("xml.png")) => %(<img alt="Xml" src="/images/xml.png" />), %(image_tag("rss.gif", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.gif" />), %(image_tag("gold.png", :size => "20")) => %(<img alt="Gold" height="20" src="/images/gold.png" width="20" />), + %(image_tag("gold.png", :size => 20)) => %(<img alt="Gold" height="20" src="/images/gold.png" width="20" />), %(image_tag("gold.png", :size => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), %(image_tag("gold.png", "size" => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), %(image_tag("error.png", "size" => "45 x 70")) => %(<img alt="Error" src="/images/error.png" />), @@ -238,6 +239,7 @@ class AssetTagHelperTest < ActionView::TestCase %(video_tag("gold.m4v", "size" => "320x240")) => %(<video height="240" src="/videos/gold.m4v" width="320"></video>), %(video_tag("trailer.ogg", :poster => "screenshot.png")) => %(<video poster="/images/screenshot.png" src="/videos/trailer.ogg"></video>), %(video_tag("error.avi", "size" => "100")) => %(<video height="100" src="/videos/error.avi" width="100"></video>), + %(video_tag("error.avi", "size" => 100)) => %(<video height="100" src="/videos/error.avi" width="100"></video>), %(video_tag("error.avi", "size" => "100 x 100")) => %(<video src="/videos/error.avi"></video>), %(video_tag("error.avi", "size" => "x")) => %(<video src="/videos/error.avi"></video>), %(video_tag("http://media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="http://media.rubyonrails.org/video/rails_blog_2.mov"></video>), diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index e1cace7d88..ff8dd6b72d 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `foreign_key_exists?` method. + + *Tõnis Simo* + * Use SQL COUNT and LIMIT 1 queries for `none?` and `one?` methods if no block or limit is given, instead of loading the entire collection to memory. This applies to relations (e.g. `User.all`) as well as associations (e.g. `account.users`) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 8cd4b8e5b2..a2777fcd0a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -50,6 +50,14 @@ module ActiveRecord options[:primary_key] != default_primary_key end + def defined_for?(options_or_to_table = {}) + if options_or_to_table.is_a?(Hash) + options_or_to_table.all? {|key, value| options[key].to_s == value.to_s } + else + to_table == options_or_to_table.to_s + end + end + private def default_primary_key "id" @@ -651,6 +659,10 @@ module ActiveRecord @base.add_foreign_key(name, *args) end + def foreign_key_exists?(*args) # :nodoc: + @base.foreign_key_exists?(name, *args) + end + private def native @base.native_database_types 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 c9180f64db..0438c95bd7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -667,7 +667,7 @@ module ActiveRecord # remove_reference(:products, :user, index: true, foreign_key: true) # def remove_reference(table_name, ref_name, options = {}) - remove_foreign_key table_name, ref_name if options[:foreign_key] + remove_foreign_key table_name, ref_name.to_s.pluralize if options[:foreign_key] remove_column(table_name, "#{ref_name}_id") remove_column(table_name, "#{ref_name}_type") if options[:polymorphic] @@ -757,21 +757,7 @@ module ActiveRecord def remove_foreign_key(from_table, options_or_to_table = {}) return unless supports_foreign_keys? - if options_or_to_table.is_a?(Hash) - options = options_or_to_table - else - options = { column: foreign_key_column_for(options_or_to_table) } - end - - fk_name_to_delete = options.fetch(:name) do - fk_to_delete = foreign_keys(from_table).detect {|fk| fk.column == options[:column].to_s } - - if fk_to_delete - fk_to_delete.name - else - raise ArgumentError, "Table '#{from_table}' has no foreign key on column '#{options[:column]}'" - end - end + fk_name_to_delete = foreign_key_for!(from_table, options_or_to_table).name at = create_alter_table from_table at.drop_foreign_key fk_name_to_delete @@ -779,6 +765,31 @@ module ActiveRecord execute schema_creation.accept(at) end + # Checks to see if a foreign key exists on a table for a given foreign key definition. + # + # # Check a foreign key exists + # foreign_key_exists?(:accounts, :branches) + # + # # Check a foreign key on specified column exists + # foreign_key_exists?(:accounts, column: :owner_id) + # + # # Check a foreign key with a custom name exists + # foreign_key_exists?(:accounts, name: "special_fk_name") + # + def foreign_key_exists?(from_table, options_or_to_table = {}) + foreign_key_for(from_table, options_or_to_table).present? + end + + def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc: + return unless supports_foreign_keys? + foreign_keys(from_table).detect {|fk| fk.defined_for? options_or_to_table } + end + + def foreign_key_for!(from_table, options_or_to_table = {}) # :nodoc: + foreign_key_for(from_table, options_or_to_table) or \ + raise ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}" + end + def foreign_key_column_for(table_name) # :nodoc: "#{table_name.to_s.singularize}_id" end diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index b2f2d077eb..7f4790bf3e 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -147,6 +147,27 @@ module ActiveRecord assert_equal :nullify, fk.on_update end + def test_foreign_key_exists + @connection.add_foreign_key :astronauts, :rockets + + assert @connection.foreign_key_exists?(:astronauts, :rockets) + assert_not @connection.foreign_key_exists?(:astronauts, :stars) + end + + def test_foreign_key_exists_by_column + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id" + + assert @connection.foreign_key_exists?(:astronauts, column: "rocket_id") + assert_not @connection.foreign_key_exists?(:astronauts, column: "star_id") + end + + def test_foreign_key_exists_by_name + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk" + + assert @connection.foreign_key_exists?(:astronauts, name: "fancy_named_fk") + assert_not @connection.foreign_key_exists?(:astronauts, name: "other_fancy_named_fk") + end + def test_remove_foreign_key_inferes_column @connection.add_foreign_key :astronauts, :rockets diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index 99d69d5eda..dd5ca4b395 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -6,4 +6,8 @@ *Andrey Nering* +* New section in Configuring: Search Engines Indexing + + *Andrey Nering* + Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/guides/CHANGELOG.md) for previous changes. diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index 93f76d3bf7..de26a9bd6d 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -606,9 +606,7 @@ This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, -you must create a unique index on both columns in your database. See -[the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html) -for more details about multiple column indexes. +you must create a unique index on that column in your database. ```ruby class Account < ActiveRecord::Base @@ -628,6 +626,7 @@ class Holiday < ActiveRecord::Base message: "should happen once per year" } end ``` +Should you wish to create a database constraint to prevent possible violations of a uniqueness validation using the `:scope` option, you must create a unique index on both columns in your database. See [the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html) for more details about multiple column indexes or [the PostgreSQL manual](http://www.postgresql.org/docs/9.4/static/ddl-constraints.html) for examples of unique constraints that refer to a group of columns. There is also a `:case_sensitive` option that you can use to define whether the uniqueness constraint will be case sensitive or not. This option defaults to diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 9c0f2ddc8a..994cc31cff 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -1049,3 +1049,21 @@ These configuration points are then available through the configuration object: Rails.configuration.x.super_debugger # => true Rails.configuration.x.super_debugger.not_set # => nil ``` + +Search Engines Indexing +----------------------- + +Sometimes, you may want to prevent some pages of your application be visible on search sites like Google, +Bing, Yahoo or Duck Duck Go. The robots that index these sites will first analyse the +`https://your-site.com/robots.txt` file to know what pages it is allowed to index. + +Rails creates this file for you on `/public` folder. By default, it allows search engines to index all +pages of your application. If you want to block indexing on all pages of you application, use this: + +``` +User-agent: * +Disallow: / +``` + +To block just specific pages, it's necessary to use a more complex syntax. Learn it on the +[official documentation](http://www.robotstxt.org/robotstxt.html). diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md index a2d2e93e3b..6113a61f4c 100644 --- a/guides/source/debugging_rails_applications.md +++ b/guides/source/debugging_rails_applications.md @@ -242,6 +242,58 @@ The contents of the block, and therefore the string interpolation, is only evaluated if debug is enabled. This performance savings is only really noticeable with large amounts of logging, but it's a good practice to employ. + +Debugging with the `web-console` gem +------------------------------------- + +The web console allows you to create an interactive ruby session in your browser. An interactive +console is launched automatically in case on an error but can also be launched for debugging purposes +by invoking `console` in a view or controller. + +For example in a view: + +```ruby +# new.html.erb +<%= console %> +``` + +Or in a controller: + +```ruby +# posts_controller.rb +class PostsController < ApplicationController + def new + console + @post = Post.new + end +end +``` +###config.web_console.whitelisted_ips + +By default the web console can only be accessed from localhost. `config.web_console.whitelisted_ips` +lets you control which IPs have access to the console. + +For example, to allow access from both localhost and 192.168.0.100: + +```ruby +# config/application.rb +class Application < Rails::Application + config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.100 ) +end +``` + +To allow access from an entire network: + +```ruby +# config/application.rb +class Application < Rails::Application + config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.0/16 ) +end +``` + +Web console is a powerful tool so be careful who you open access to. + + Debugging with the `byebug` gem --------------------------------- diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md index f3d3a83afc..e3856a285a 100644 --- a/guides/source/working_with_javascript_in_rails.md +++ b/guides/source/working_with_javascript_in_rails.md @@ -191,6 +191,34 @@ $(document).ready -> Obviously, you'll want to be a bit more sophisticated than that, but it's a start. You can see more about the events [in the jquery-ujs wiki](https://github.com/rails/jquery-ujs/wiki/ajax). +Another possibility is returning javascript directly from the server side on +remote calls: + +```ruby +# articles_controller +def create + respond_to do |format| + if @article.save + format.html { ... } + format.js do + render js: <<-endjs + alert('Article saved successfully!'); + window.location = '#{article_path(@article)}'; + endjs + end + else + format.html { ... } + format.js do + render js: "alert('There are empty fields in the form!');" + end + end + end +end +``` + +NOTE: If javascript is disabled in the user browser, `format.html { ... }` +block should be executed as fallback. + ### form_tag [`form_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag) |