├── README.md ├── contributing.md ├── git_template.md ├── rails_tip ├── 2016-02-12-duplicate_remove_with_options.md ├── 2016-02-13-strip-or-squish.md ├── 2016-02-14-efficiency_of_pluck.md ├── 2016-02-15-formatting_numbers.md ├── 2016-02-16-unscope_unwanted_relation.md ├── 2016-02-17-rails_console_with_sandbox_mode.md ├── 2016-02-18-routes_with_pattern.md ├── 2016-02-19-enable_caching_for_develpment_with_command.md ├── 2016-02-20-length_vs_size_vs_count.md ├── 2016-02-21-puts_vs_p.md ├── 2016-02-22-change_and_up_down_migration.md ├── 2016-02-23-disable_multiple_submit using_disable_with.md ├── 2016-02-24-same_time_option_to_next_and_prev_week_rails5.md ├── 2016-02-25-rendering_views_outside_of_controllers.md ├── 2016-02-26-use-enums-in-model.md ├── 2016-02-27-rails_inquiry.md ├── 2016-02-28-custom_mailer_queue_name.md ├── 2016-02-29-redirect_back_with_fallback.md ├── 2016-03-01-rails_5_migration_feature_additions.md ├── 2016-03-02-pluck_added_to_enumerable_rails_5.md ├── 2016-03-03-debug_exception_response_format.md ├── 2016-03-04-rails_console_auto_complete.md ├── 2016-03-05-http_cache_forever_rails_5.md ├── 2016-03-06-filter_parameter_enhancements_rails_5.md ├── 2016-03-07-Interaction_to_app_from_console.md ├── 2016-03-08-Increase_productivity_with_few_tricks.md ├── 2016-03-09-rendering_partial_from_cache_faster.md ├── 2016-03-10-left_outer_join_in_Rails_5.md └── 2016-03-29-Retrieving ids.md └── tip_template.md /README.md: -------------------------------------------------------------------------------- 1 | # Rails Tips [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome) 2 | 3 | ##Rails tip for the day 4 | 5 | Being impressed with the awesomeness of jstip repository, I came up with the idea of tips that will allow rails community also to improve. No matter what the tip is going to be "either a small one or best one" but it will be useful for some one or the other at their level and infact higher. 6 | 7 | Please feel free to send us a pull request with your Rails tip to be published here. Any improvements or suggestions are more than welcome! 8 | 9 | # Tips list 10 | - 28 - [Support for left outer join in rails 5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-10-left_outer_join_in_Rails_5.md) 11 | - 27 - [Render partial from cache faster](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-09-rendering_partial_from_cache_faster.md) 12 | - 26 - [Increase productivity with console tricks](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-08-Increase_productivity_with_few_tricks.md) 13 | - 25 - [Issuing request interactively from rails console](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-07-Interaction_to_app_from_console.md) 14 | - 24 - [Filter parameter improvements rails 5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-06-filter_parameter_enhancements_rails_5.md) 15 | - 23 - [http_cache_forever rails 5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-05-http_cache_forever_rails_5.md) 16 | - 22 - [Rails console autocomplete](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-04-rails_console_auto_complete.md) 17 | - 21 - [Throw exception in the request format](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-03-debug_exception_response_format.md) 18 | - 20 - [Pluck method added to enumerable in rails 5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-02-pluck_added_to_enumerable_rails_5.md) 19 | - 19 - [Additional features of rails 5 migration](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-03-01-rails_5_migration_feature_additions.md) 20 | - 18 - [redirect_back in rails5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-29-redirect_back_with_fallback.md) 21 | - 17 - [Customize mailer queue name](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-28-custom_mailer_queue_name.md) 22 | - 16 - [Inquiry in rails](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-27-rails_inquiry.md) 23 | - 15 - [Using enums in model](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-26-use-enums-in-model.md) 24 | - 14 - [Render views outside controller rails 5](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-25-rendering_views_outside_of_controllers.md) 25 | - 13 - [Get same time of next and previous week](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-24-same_time_option_to_next_and_prev_week_rails5.md) 26 | - 12 - [Disable multiple submission using data_diasble_with attr](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-23-disable_multiple_submit using_disable_with.md) 27 | - 11 - [Migration using change vs up down methods](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-22-change_and_up_down_migration.md) 28 | - 10 - [Difference between puts and p](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-21-puts_vs_p.md) 29 | - 09 - [length vs size vs count](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-20-length_vs_size_vs_count.md) 30 | - 08 - [Enabling cache without app restart in dev env](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-19-enable_caching_for_develpment_with_command.md) 31 | - 07 - [Routes with pattern](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-18-routes_with_pattern.md) 32 | - 06 - [Rails sandbox console](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-17-rails_console_with_sandbox_mode.md) 33 | - 05 - [Unscope unwanted relation](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-16-unscope_unwanted_relation.md) 34 | - 04 - [Format numbers to different Formats](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-15-formatting_numbers.md) 35 | - 03 - [Efficiency of pluck](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-14-efficiency_of_pluck.md) 36 | - 02 - [Where use strip or squish](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-13-strip-or-squish.md) 37 | - 01 - [Remove duplicates using with_options](https://github.com/logeshmallow/rails_tips/blob/master/rails_tip/2016-02-12-duplicate_remove_with_options.md) 38 | 39 | # License 40 |

41 | 43 | CC0 44 | 45 |
46 | 47 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # How to submit your tip 2 | 3 | To submit a tip to the list, fork the repository and add your tip to a new file in the rails_tip folder. The name of the file should be `YYYY-MM-DD-tip-name`. 4 | 5 | Use [this format](https://github.com/logeshmallow/rails_tips/blob/master/tip_template.md) when writing your tip. Your tip should be brief. You may add links to other sites or videos that give more insight if you wish. 6 | 7 | Once your tip is ready, issue a pull request with this [PR template](https://github.com/logeshmallow/rails_tips/blob/master/git_template.md) and your tip will be reviewed. Every day one tip will be merged from the available pull requests. 8 | -------------------------------------------------------------------------------- /git_template.md: -------------------------------------------------------------------------------- 1 | ## [Title here] 2 | 3 | ## Username 4 | 5 | ## Extra 6 | [content here] 7 | -------------------------------------------------------------------------------- /rails_tip/2016-02-12-duplicate_remove_with_options.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Remove duplicate passed to series of method using with_options 3 | tip-number: 01 4 | tip-username: logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Removing duplicates out of options passed to a series of methods and avoid more bugs from forgetting to add the necessary options. 7 | 8 | --- 9 | 10 | An elegant way to factor duplication out of options passed to a series of method calls. Each method called in the block, with the block variable as the receiver, will have its options merged with the default options hash provided. Each method called on the block variable must take an options hash as its final argument. 11 | 12 | We usually had this dependent called every time and we certainly missed few times unnoticed as shown below 13 | 14 | ```ruby 15 | class User < ActiveRecord::Base 16 | has_many :sample1, class_name: "User", dependent: :destroy 17 | has_many :sample2, dependent: :destroy 18 | has_many :sample3, as: :test 19 | end 20 | ``` 21 | 22 | In the above code we have duplicates and we have also missed dependent in one of our association. So for such scenarios, we can have the with_options used as shown below 23 | 24 | ```ruby 25 | class User < ActiveRecord::Base 26 | with_options dependent: :destroy do |assoc| 27 | assoc.has_many :sample1, class_name: "User" 28 | assoc.has_many :sample2 29 | assoc.has_many :sample3, as: :test 30 | end 31 | end 32 | ``` 33 | 34 | I hope the above tip will be useful. 35 | -------------------------------------------------------------------------------- /rails_tip/2016-02-13-strip-or-squish.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Where use strip or squish 3 | tip-number: 02 4 | tip-username: logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Removing leading or trailing spaces can be done using both methods but squish also substitutes single space with multiple spaces in between string. 7 | 8 | --- 9 | 10 | We use strip to remove leading and trailing spaces. But some times, we require removing spaces between strings or substitute mistakenly typed two or more spaces with one space and for that case, we can use squish. 11 | 12 | ##strip: 13 | 14 | Returns a copy of str with leading and trailing whitespace removed 15 | 16 | ```ruby 17 | " mallow ".strip #=> "mallow" 18 | "\trails dev\r\n".strip #=> "rails dev" 19 | " foo bar ".strip #=> 0.005ms 20 | ``` 21 | 22 | ##squish: 23 | 24 | Returns the string, first removing all whitespace on both ends of the string, and then changing remaining consecutive whitespace groups into one space each. 25 | 26 | ```ruby 27 | %{ Multi-line 28 | string }.squish # => "Multi-line string" 29 | " foo bar \n \t boo".squish # => "foo bar boo" 30 | " foo bar ".squish #=> 0.029ms 31 | ``` 32 | 33 | I hope the above tip will be useful. 34 | -------------------------------------------------------------------------------- /rails_tip/2016-02-14-efficiency_of_pluck.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Efficiency of pluck 3 | tip-number: 03 4 | tip-username: logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Pluck can be used to select one or more attributes without loading a bunch of records just to grab the attributes you want. 7 | 8 | --- 9 | 10 | We often come through the requirement of selecting a particular attribute or few attributes and we use few methods to do this like pluck, select and map/collect and we are not certain on how efficient are those. 11 | 12 | ##map/collect with select: 13 | 14 | Basically these 2 methods are alias of each other, thus they do one and the same thing. 15 | 16 | ```ruby 17 | User.select(:id).collect(&:id) 18 | User.select(:id).map(&:id) 19 | User Load (0.5ms) SELECT "users"."id" FROM "users" 20 | Benchmark.ms{User.select(:id).collect(&:id)} => 1.824394003051566 21 | ``` 22 | 23 | ##pluck: 24 | 25 | Can be used to select one or more attributes without loading a bunch of records just to grab the attributes you want. 26 | 27 | ```ruby 28 | User.pluck(:id) 29 | (0.5ms) SELECT "users"."id" FROM "users" 30 | Benchmark.ms{User.pluck(:id)} => 1.1335880008118693 31 | ``` 32 | 33 | We can select multiple attributes by using both these but here is the difference 34 | 35 | ```ruby 36 | Benchmark.ms{User.select(:id, :email).collect{|x| [x.id, x.email]}} 37 | User Load (0.5ms) SELECT "users"."id", "users"."email" FROM "users" 38 | => 1.79159800245543 39 | ``` 40 | 41 | ```ruby 42 | Benchmark.ms{User.pluck(:id, :email)} 43 | (0.5ms) SELECT "users"."id", "users"."email" FROM "users" 44 | => 1.2821059972338844 45 | ``` 46 | 47 | The SQL query executed in both the cases is exactly the same, but time taken by pluck approach is considerably less than that of collect/map with select. 48 | 49 | I hope the above tip will be useful. 50 | -------------------------------------------------------------------------------- /rails_tip/2016-02-15-formatting_numbers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Formatting numbers to different representation. 3 | tip-number: 04 4 | tip-username: logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We represent numbers in different format and this could be done easily using number of ways listed below. 7 | 8 | --- 9 | 10 | Below are list of representations 11 | 12 | #### Telephone number 13 | ```ruby 14 | 1235551234.to_s(:phone, country_code: 1) # => +1-123-555-1234 15 | ``` 16 | 17 | #### Currency 18 | ```ruby 19 | 1234567890.506.to_s(:currency, precision: 3) # => $1,234,567,890.506 20 | ``` 21 | 22 | #### Percentage 23 | ```ruby 24 | 1000.to_s(:percentage, delimiter: '.', separator: ',') # => 1.000,000% 25 | ``` 26 | 27 | #### Delimited 28 | ```ruby 29 | 12345678.to_s(:delimited, delimiter: ",") # => 12,345,678 30 | ``` 31 | 32 | #### Rounded 33 | ```ruby 34 | 111.2345.to_s(:rounded, significant: true) # => 111 35 | ``` 36 | 37 | #### Human size 38 | ```ruby 39 | 1234567.to_s(:human_size) # => 1.18 MB 40 | ``` 41 | 42 | #### Human 43 | ```ruby 44 | 12345.to_s(:human) # => "12.3 Thousand" 45 | ``` 46 | 47 | I hope the above tip will be useful. 48 | -------------------------------------------------------------------------------- /rails_tip/2016-02-16-unscope_unwanted_relation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Unscope to remove or modify the unwanted relation 3 | tip-number: 05 4 | tip-username: logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We can remove or modify the unwanted relation that is already defined on a chain of relations. This would be useful when modifying relations without reconstructing entire chain. 7 | 8 | --- 9 | 10 | ```ruby 11 | User.order(‘email DESC’).unscope(:order) == User.all 12 | ``` 13 | 14 | We can also call this method with multiple arguments as 15 | 16 | ```ruby 17 | User.order(‘email DESC’).select(‘id’).unscope(:order, :select) == User.all 18 | ``` 19 | 20 | Also, we can unscope :where values like 21 | 22 | ```ruby 23 | User.where(name: “mallow”, active: true).unscope(where: :name) == User.where(active: true) 24 | ``` 25 | 26 | We can use in association definition 27 | 28 | ```ruby 29 | has_many :posts, -> { unscope where: :removed } 30 | ``` 31 | 32 | I hope the above tip will be useful. 33 | -------------------------------------------------------------------------------- /rails_tip/2016-02-17-rails_console_with_sandbox_mode.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Run rails console in sandbox mode 3 | tip-number: 06 4 | tip-username: prakash 5 | tip-username-profile: https://github.com/prakashROR 6 | tip-description: In sandbox mode, any database changes made while in the console will be reverted when you exit the console. 7 | --- 8 | 9 | This feature comes in handy any time we need to run methods from the console without permanently changing data. 10 | For example, when trying to reproduce reported bugs in production, we can use the sandbox mode to make sure we don’t accidentally change existing user data. 11 | 12 | ```ruby 13 | rails c --sandbox 14 | Loading development environment in sandbox (Rails 5.0.0.beta2) 15 | Any modifications you make will be rolled back on exit 16 | 2.3.0 :001 > User.count 17 | (0.7ms) SELECT COUNT(*) FROM "users" 18 | => 10 19 | 2.3.0 :002 > User Load (1.0ms) SELECT "users".* FROM "users" 20 | (0.2ms) SAVEPOINT active_record_1 21 | SQL (0.6ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 14]] 22 | (0.1ms) RELEASE SAVEPOINT active_record_1 23 | (0.1ms) SAVEPOINT active_record_1 24 | SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 15]] 25 | (0.1ms) RELEASE SAVEPOINT active_record_1 26 | (0.1ms) SAVEPOINT active_record_1 27 | SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 18]] 28 | (0.2ms) RELEASE SAVEPOINT active_record_1 29 | (0.1ms) SAVEPOINT active_record_1 30 | SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 19]] 31 | (0.1ms) RELEASE SAVEPOINT active_record_1 32 | (0.1ms) SAVEPOINT active_record_1 33 | SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 24]] 34 | (0.2ms) RELEASE SAVEPOINT active_record_1 35 | (0.1ms) SAVEPOINT active_record_1 36 | SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 1]] 37 | (0.2ms) RELEASE SAVEPOINT active_record_1 38 | (0.1ms) SAVEPOINT active_record_1 39 | SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 25]] 40 | (0.1ms) RELEASE SAVEPOINT active_record_1 41 | (0.2ms) SAVEPOINT active_record_1 42 | SQL (0.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 27]] 43 | (0.1ms) RELEASE SAVEPOINT active_record_1 44 | (0.2ms) SAVEPOINT active_record_1 45 | SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 26]] 46 | (0.1ms) RELEASE SAVEPOINT active_record_1 47 | (0.1ms) SAVEPOINT active_record_1 48 | SQL (0.3ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 28]] 49 | (0.1ms) RELEASE SAVEPOINT active_record_1 50 | [...] 51 | 2.3.0 :003 > User.count 52 | (0.4ms) SELECT COUNT(*) FROM "users" 53 | => 0 54 | 2.3.0 :004 > exit 55 | (0.3ms) ROLLBACK 56 | ``` 57 | 58 | 59 | Hope this is useful.. 60 | -------------------------------------------------------------------------------- /rails_tip/2016-02-18-routes_with_pattern.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pattern matching on Routes 3 | tip-number: 07 4 | tip-username: Surender Thillainathan 5 | tip-username-profile: https://github.com/harrysuren 6 | tip-description: Getting the desired routes which matches the given pattern/string 7 | 8 | --- 9 | 10 | ### Rails 4 and below 11 | 12 | `rake routes` will give us the available routes in a Project. 13 | 14 | If we need to get only some routes which all are related to the User. 15 | 16 | Its will gives us the routes which are matches to the pattern 'user' 17 | 18 | ```ruby 19 | $ rake routes | grep user 20 | new_user_session GET /login(.:format) devise/sessions#new 21 | user_session POST /login(.:format) devise/sessions#create 22 | destroy_user_session DELETE /sign_out(.:format) devise/sessions#destroy 23 | user_password POST /reset(.:format) devise/passwords#create 24 | new_user_password GET /reset/new(.:format) devise/passwords#new 25 | edit_user_password GET /reset/edit(.:format) devise/passwords#edit 26 | ``` 27 | 28 | ### Rails 5 29 | 30 | We can use both `rake routes` and `rails routes` to get all the available routes for a Project 31 | 32 | 33 | `Rails 5` added some options to routes 34 | 35 | To get Controller specific routes we can use the option `-c` 36 | 37 | ```ruby 38 | # Controller name 39 | $ rake routes -c users 40 | all_users GET /users(.:format) users#index 41 | new_user GET /users/new(.:format) users#new 42 | create_user POST /additional_users(.:format) users#create 43 | update_user PATCH /additional_users/:id(.:format) users#update 44 | edit_user GET /users/:id/edit(.:format) users#edit 45 | 46 | ``` 47 | 48 | 49 | ```ruby 50 | # Namespaced Controller 51 | $ rake routes -c admin/users 52 | all_users GET /users(.:format) users#index 53 | new_user GET /users/new(.:format) users#new 54 | create_user POST /additional_users(.:format) users#create 55 | update_user PATCH /additional_users/:id(.:format) users#update 56 | edit_user GET /users/:id/edit(.:format) users#edit 57 | 58 | ``` 59 | 60 | 61 | ```ruby 62 | # Namespaced Controller 63 | $ rake routes -c Admin::UsersController 64 | all_users GET /users(.:format) users#index 65 | new_user GET /users/new(.:format) users#new 66 | create_user POST /additional_users(.:format) users#create 67 | update_user PATCH /additional_users/:id(.:format) users#update 68 | edit_user GET /users/:id/edit(.:format) users#edit 69 | 70 | ``` 71 | 72 | 73 | To get teh Pattern matched routes like `grep` we can use the option `-g' 74 | 75 | 76 | ```ruby 77 | # Search with HTTP verb 78 | $ rake routes -g GET 79 | all_users GET /users(.:format) users#index 80 | new_user GET /users/new(.:format) users#new 81 | edit_user GET /users/:id/edit(.:format) users#edit 82 | ``` 83 | 84 | 85 | ```ruby 86 | # Search with pattern 87 | $ rake routes -g password 88 | user_password POST /reset(.:format) devise/passwords#create 89 | new_user_password GET /reset/new(.:format) devise/passwords#new 90 | edit_user_password GET /reset/edit(.:format) devise/passwords#edit 91 | ``` 92 | -------------------------------------------------------------------------------- /rails_tip/2016-02-19-enable_caching_for_develpment_with_command.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Enabling caching for development without restarting the app. 3 | tip-number: 08 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Enable caching in development mode without restarting the app using the command 7 | 8 | --- 9 | 10 | ### Rails 4 11 | 12 | In rails4 we need to turn caching “on” by opening file config/environments/development.rb and changing following line. 13 | 14 | ```ruby 15 | config.action_controller.perform_caching = false 16 | ``` 17 | 18 | After changing the value from false to true, I need to restart the server. 19 | 20 | This means that if I am testing caching behavior locally then every time I turn caching “on” or “off” I need to restart the server. 21 | 22 | 23 | ### Rails 5 24 | 25 | Rails 5 has introduced a new command to create development cache and help us test how caching behaves in development mode. Here is the issue and here is the pull request. 26 | 27 | ```ruby 28 | $ rails dev:cache 29 | Development mode is now being cached. 30 | ``` 31 | Execution of the above command creates file caching-dev.txt in tmp directory. 32 | 33 | Advantage: 34 | 35 | The advantage is that we do not need to restart the server manually if we want to turn caching “on” or “off”. It is internally taken care by the dev_cache method that is executed when rails dev:cache is executed. 36 | 37 | Please note that this feature is not supported by unicorn, thin and webrick. 38 | 39 | Disabling development cache: 40 | 41 | Execute the same command that was used to enable caching. If caching was previously enabled then it will be turned “off” now. 42 | 43 | ```ruby 44 | $ rails dev:cache 45 | Development mode is no longer being cached. 46 | ``` -------------------------------------------------------------------------------- /rails_tip/2016-02-20-length_vs_size_vs_count.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: length vs size vs count 3 | tip-number: 09 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: These are similar ones which can be used in Arrays, Hashes or Objects. So where to use these and why is what is covered here. 7 | 8 | --- 9 | 10 | ### length 11 | 12 | Basically length method used on arrays in ruby returns number of elements in the array for which method is invoked. 13 | 14 | Example, suppose we have array a as, 15 | 16 | ```ruby 17 | a = [1,2,3,4,5,6,7] 18 | a.length 19 | => 7 20 | ``` 21 | 22 | ### size 23 | 24 | Size is just an alias to the Array#length method. It executes same Array#length method internally. 25 | 26 | Example, 27 | 28 | ```ruby 29 | b = [1,2,3,4] 30 | b.size 31 | => 4 32 | ``` 33 | 34 | ### count 35 | 36 | Count has some more functionalities than length/size. It can be used for getting number of elements based on some condition. 37 | 38 | Example: 39 | 40 | Suppose we have array c as, 41 | 42 | ```ruby 43 | c = [1,2,3,4,4,7,7,7,9] 44 | c.count 45 | => 9 46 | 47 | c.count 7 48 | => 3 49 | 50 | c.count {|i| i>5} 51 | => 4 52 | ``` 53 | 54 | Array#count should be used only for getting number of elements in array based on some condition. 55 | 56 | Otherwise, for getting number of elements without any condition use Array#length or Array#size. -------------------------------------------------------------------------------- /rails_tip/2016-02-21-puts_vs_p.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Difference between puts and p 3 | tip-number: 10 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Both puts and p are used for printing but then what the difference is covered here. 7 | 8 | --- 9 | 10 | ### puts 11 | 12 | When you use puts for printing, then puts internally uses to_s on objects before processing inputs, while p uses inspect on objects before processing inputs. 13 | 14 | E.g. Again considering same example, 15 | 16 | ```ruby 17 | user = User.first 18 | puts user 19 | # 20 | ``` 21 | 22 | This just has converted object's reference using to_s 23 | 24 | ### p 25 | 26 | ```ruby 27 | p user 28 | # 29 | ``` 30 | 31 | Thus, you may prefer using p instead of to_s if you are looking purely for logging/ debugging purposes. Otherwise use of these methods purely depends on the required functionality though. 32 | 33 | -------------------------------------------------------------------------------- /rails_tip/2016-02-22-change_and_up_down_migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Migration Change vs Up Down Methods 3 | tip-number: 11 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We should write migrations with change method if we are not migrating database with manual update, if we are, then we should consider using up down methods and write behaviour that handles the manual update we want. 7 | 8 | --- 9 | 10 | ### change 11 | 12 | We do not need to write specific down method if we use change method to write migrations 13 | 14 | Rails automatically can detect what needs to be reverted considering what was changed in change method 15 | 16 | Revert to this type of migrations works only when they are written by Rails Conventions only - like given above using, add_column, remove_column, create_table and so on. 17 | 18 | When we try to revert, Rails will not be able to detect manual changes done in change method. e.g. If you alter database with 19 | 20 | ```ruby 21 | class AddNameToUser < ActiveRecord::Migration 22 | 23 | def change 24 | add_column :users , :name, :string, :null => false 25 | end 26 | 27 | end 28 | ``` 29 | 30 | 31 | ### up down methods 32 | 33 | We need to define exclusively what should happen when running migration or reverting migration. 34 | 35 | Only those changes defined by us in up/down methods will be performed by Rails. 36 | 37 | We get more flexibility of defining behaviour for manual updates of database 38 | 39 | ```ruby 40 | class AddNameColumnToUser < ActiveRecord::Migration 41 | 42 | def self.up 43 | add_column :users , :name, :string, :null => false 44 | end 45 | 46 | def self.down 47 | remove_column :users , :name, :string, :null => false 48 | end 49 | 50 | end 51 | ``` 52 | -------------------------------------------------------------------------------- /rails_tip/2016-02-23-disable_multiple_submit using_disable_with.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Disable multiple time form submit using disable_with attribute 3 | tip-number: 12 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Value of this parameter will be used as the value for a disabled version of the submit button when the form is submitted. This feature is provided by the unobtrusive JavaScript driver. 7 | 8 | --- 9 | 10 | 11 | To avoid duplicate form submissions, Rails has a nice option for submit tags: 12 | 13 | ```ruby 14 | submit_tag "Submit", :disable_with => "Saving..." 15 | ``` 16 | 17 | This adds behavior to the submit button to disable it once clicked, and to display "Saving..." instead of "Submit". 18 | 19 | ### Rails 4+ 20 | 21 | ```ruby 22 | submit_tag 'Submit', data: { disable_with: 'Text' } 23 | ``` -------------------------------------------------------------------------------- /rails_tip/2016-02-24-same_time_option_to_next_and_prev_week_rails5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Get same time of next week and previous week in rails 5 3 | tip-number: 13 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We can get the next week or the previous week with the current time using this methods. 7 | 8 | --- 9 | 10 | 11 | Support for same_time option to next_week and prev_week 12 | 13 | In Rails 4.x next_week returns beginning of next week and prev_week returns beginning of previous week. 14 | 15 | In Rails 4.x these two methods also accept week day as a parameter. 16 | 17 | ```ruby 18 | Time.current 19 | => Fri, 12 Feb 2016 08:53:31 UTC +00:00 20 | 21 | Time.current.next_week 22 | => Mon, 15 Feb 2016 00:00:00 UTC +00:00 23 | 24 | Time.current.next_week(:tuesday) 25 | => Tue, 16 Feb 2016 00:00:00 UTC +00:00 26 | 27 | Time.current.prev_week(:tuesday) 28 | => Tue, 02 Feb 2016 00:00:00 UTC +00:00 29 | ``` 30 | 31 | By using week day as parameter we can get the date one week from now but the returned date is still the beginning of that date. How do we get one week from the current time. 32 | 33 | Rails 5 add an additional option same_time: true to solve this problem. 34 | 35 | Using this option, we can now get next week date from the current time. 36 | 37 | ```ruby 38 | Time.current 39 | => Fri, 12 Feb 2016 09:15:10 UTC +00:00 40 | 41 | Time.current.next_week 42 | => Mon, 15 Feb 2016 00:00:00 UTC +00:00 43 | 44 | Time.current.next_week(same_time: true) 45 | => Mon, 15 Feb 2016 09:15:20 UTC +00:00 46 | 47 | Time.current.prev_week 48 | => Mon, 01 Feb 2016 00:00:00 UTC +00:00 49 | 50 | Time.current.prev_week(same_time: true) 51 | => Mon, 01 Feb 2016 09:16:50 UTC +00:00 52 | ``` -------------------------------------------------------------------------------- /rails_tip/2016-02-25-rendering_views_outside_of_controllers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rendering views outside of controllers in Rails 5 3 | tip-number: 14 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Sometimes we want to render our HTML or JSON response outside of this request-response cycle and there we can use this option. 7 | 8 | --- 9 | 10 | 11 | Rails 5 has this feature baked in. 12 | 13 | Let’s say we have a OrdersController and we want to render individual order outside of controller. 14 | 15 | Fire up rails console and execute following command. 16 | 17 | ```ruby 18 | OrdersController.render :show, assigns: { order: Order.last } 19 | ``` 20 | 21 | This will render app/views/orders/show.html.erb with @order set to Order.last. Instance variables can be set using assigning the same way we use them in controller actions. Those instance variables will be passed to the view that is going to be rendered. 22 | 23 | Rendering partials is also possible. 24 | 25 | ```ruby 26 | OrdersController.render :_form, locals: { order: Order.last } 27 | ``` 28 | 29 | This will render app/views/orders/_form.html.erb and will pass order as local variable. 30 | 31 | Say I want to render all orders, but in JSON format. 32 | 33 | ```ruby 34 | OrdersController.render json: Order.all 35 | # => "[{"id":1, "name":"The Well-Grounded Rubyist", "author":"David A. Black"}, 36 | {"id":2, "name":"Remote: Office not required", "author":"David & Jason"}] 37 | ``` 38 | 39 | Even rendering simple text is possible. 40 | 41 | ```ruby 42 | >> BooksController.render plain: 'this is awesome!' 43 | Rendered text template (0.0ms) 44 | # => "this is awesome!" 45 | ``` 46 | 47 | Similar to text, we can also use render file and render template. 48 | 49 | -------------------------------------------------------------------------------- /rails_tip/2016-02-26-use-enums-in-model.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Use enums in models 3 | tip-number: 15 4 | tip-username: Jayaprakash 5 | tip-username-profile: https://github.com/JPMallow 6 | tip-description: How to use enums in Rails models? 7 | 8 | --- 9 | 10 | ###enums 11 | 12 | Advantage: 13 | The column in the database can be integer type, but can access that column through enum. 14 | 15 | ```ruby 16 | Class Task < ActiveRecord::Base 17 | enum status: { to_do: 0, in_progress: 1, completed: 2 } 18 | end 19 | ``` 20 | 21 | Accessing enums in controller methods 22 | 23 | ```ruby 24 | Task.statuses[:to_do] #=> "0" 25 | Task.statuses[:in_progress] #=> "1" 26 | Task.statuses[:completed] #=> "2" 27 | ``` 28 | 29 | I hope this is useful. 30 | -------------------------------------------------------------------------------- /rails_tip/2016-02-27-rails_inquiry.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Inquiry in rails 3 | tip-number: 16 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: The inquiry method provides friendlier way to check both string and array using the StringInquirer and ArrayInquirer 7 | 8 | --- 9 | 10 | The inquiry method converts a string into a StringInquirer object making equality checks prettier. 11 | 12 | ```ruby 13 | "production".inquiry.production? # => true 14 | "active".inquiry.inactive? # => false 15 | ``` 16 | 17 | Array#inquiry is a shortcut for wrapping the receiving array in an ArrayInquirer 18 | 19 | ```ruby 20 | users = [:mark, :max, :david] 21 | 22 | array_inquirer1 = ActiveSupport::ArrayInquirer.new(users) 23 | 24 | # creates ArrayInquirer object which is same as array_inquirer1 above 25 | array_inquirer2 = users.inquiry 26 | 27 | array_inquirer2.class 28 | => ActiveSupport::ArrayInquirer 29 | 30 | # provides methods like: 31 | 32 | array_inquirer2.mark? 33 | => true 34 | 35 | array_inquirer2.john? 36 | => false 37 | 38 | array_inquirer2.any?(:john, :mark) 39 | => true 40 | 41 | array_inquirer2.any?(:mark, :david) 42 | => true 43 | 44 | array_inquirer2.any?(:john, :louis) 45 | => false 46 | ``` -------------------------------------------------------------------------------- /rails_tip/2016-02-28-custom_mailer_queue_name.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom queue name for mailer 3 | tip-number: 17 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We can customise the queue name of the mailer rather than to have the default name that is assigned. 7 | 8 | --- 9 | 10 | In Rails 4.2, Active Job was integrated with Action Mailer to send emails asynchronously. 11 | 12 | Rails provides deliver_later method to enqueue mailer jobs. 13 | 14 | All outgoing mails are given the queue named “mailers” and we do not have the option of changing this queue name from “mailers” to anything else. 15 | 16 | In Rails 5, we can now change queue name for mailer jobs using following configuration. 17 | 18 | ```ruby 19 | config.action_mailer.deliver_later_queue_name = 'testqueue' 20 | ``` 21 | 22 | ```ruby 23 | class TestMailer < ApplicationMailer 24 | def send_msg(dev) 25 | @developer = dev 26 | mail(to: dev.email) 27 | end 28 | end 29 | 30 | 2.2.3 :004 > dev = Developer.first 31 | => 32 | 33 | 2.2.3 :005 > TestMailer.send_msg(dev).deliver_later 34 | => ], @job_id=“876543r3-456e-3b1c-9264-9876tr54re32”, @queue_name="testqueue", @priority=nil> 35 | ``` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rails_tip/2016-02-29-redirect_back_with_fallback.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: redirect_back with fallback location 3 | tip-number: 18 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We can redirect to the previous page using redirect_back and avoid HTTP_REFERER error using fallback location instead of rescue 7 | 8 | --- 9 | 10 | In Rails 4.x, for going back to previous page we use redirect_to :back. 11 | 12 | However sometimes we get ActionController::RedirectBackError exception when HTTP_REFERER is not present. 13 | 14 | To avoid this exception we can use rescue and redirect to root url. 15 | 16 | ```ruby 17 | class PostsController < ApplicationController 18 | rescue_from ActionController::RedirectBackError, with: :redirect_to_default 19 | 20 | def publish 21 | post = Post.find params[:id] 22 | post.publish! 23 | redirect_to :back 24 | end 25 | 26 | private 27 | 28 | def redirect_to_default 29 | redirect_to root_path 30 | end 31 | end 32 | ``` 33 | 34 | In Rails 5, redirect_to :back has been deprecated and instead a new method has been added called redirect_back. 35 | 36 | To deal with the situation when HTTP_REFERER is not present, it takes required option fallback_location. 37 | 38 | ```ruby 39 | class PostsController < ApplicationController 40 | 41 | def publish 42 | post = Post.find params[:id] 43 | post.publish! 44 | 45 | redirect_back(fallback_location: root_path) 46 | end 47 | end 48 | ``` 49 | 50 | This redirects to HTTP_REFERER when it is present and when HTTP_REFERER is not present then redirects to whatever is passed as fallback_location. -------------------------------------------------------------------------------- /rails_tip/2016-03-01-rails_5_migration_feature_additions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: rails 5 migration feature additions 3 | tip-number: 19 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Rails 5 has changed migration API where not null is automatically added for timestamps and sets index for reference columns 7 | 8 | --- 9 | 10 | In Rails 4.x command 11 | 12 | rails g model User name:string 13 | 14 | will generate migration as shown below. 15 | 16 | ```ruby 17 | class CreatePosts < ActiveRecord::Migration[5.0] 18 | def change 19 | create_table :posts do |t| 20 | t.string :title 21 | 22 | t.timestamps null: false 23 | end 24 | end 25 | end 26 | ``` 27 | 28 | In Rails 5 the same command will generate following migration. 29 | 30 | ```ruby 31 | class CreatePosts < ActiveRecord::Migration[5.0] 32 | def change 33 | create_table :posts do |t| 34 | t.string :title 35 | 36 | t.timestamps 37 | end 38 | end 39 | end 40 | ``` 41 | 42 | But the schema generated after running migration in rails 5 would be 43 | 44 | ```ruby 45 | sqlite> .schema posts 46 | CREATE TABLE "posts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL); 47 | sqlite> 48 | ``` 49 | 50 | In Rails 4.x command 51 | 52 | rails g model Task user:references 53 | 54 | would generate following migration. 55 | 56 | ```ruby 57 | class CreateTasks < ActiveRecord::Migration 58 | def change 59 | create_table :tasks do |t| 60 | t.references :user, index: true, foreign_key: true 61 | t.timestamps null: false 62 | end 63 | end 64 | end 65 | ``` 66 | 67 | In Rails 5.0, same command will generate following migration. 68 | 69 | ```ruby 70 | class CreateTasks < ActiveRecord::Migration[5.0] 71 | def change 72 | create_table :tasks do |t| 73 | t.references :user, foreign_key: true 74 | 75 | t.timestamps 76 | end 77 | end 78 | end 79 | ``` 80 | 81 | There is no mention of index: true in the above migration. Let’s see the generated schema after running Rails 5 migration. 82 | 83 | ```ruby 84 | sqlite> .schema tasks 85 | CREATE TABLE "tasks" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "user_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL); 86 | 87 | CREATE INDEX "index_tasks_on_user_id" ON "tasks" ("user_id"); 88 | ``` 89 | 90 | If we look closer at the migrations of rails 5, you could see class is now inheriting from ActiveRecord::Migration[5.0] instead of ActiveRecord::Migration and this indicates the migration is created from rails 5 -------------------------------------------------------------------------------- /rails_tip/2016-03-02-pluck_added_to_enumerable_rails_5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: pluck added to enumerable in rails 5 3 | tip-number: 20 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Due to this addition of method, when relation is already loaded then instead of firing query with pluck, it uses Enumerable#pluck to get data. 7 | 8 | --- 9 | 10 | ### With Rails 4.x 11 | 12 | ```ruby 13 | users = User.all 14 | SELECT `users`.* FROM `users` 15 | 16 | users.pluck(:id, :name) 17 | SELECT "users"."id", "users"."name" FROM "users" 18 | 19 | => [[2, "Balakarthik"], [3, "Gokul"], [4, "ArunPandi"]] 20 | ``` 21 | 22 | ### With Rails 5 23 | 24 | ```ruby 25 | users = User.all 26 | SELECT "users".* FROM "users" 27 | 28 | # does not fire any query 29 | users.pluck(:id, :name) 30 | => [[1, "Premanandh"], [2, "Balakarthik"], [3, "Gokul"]] 31 | ``` 32 | -------------------------------------------------------------------------------- /rails_tip/2016-03-03-debug_exception_response_format.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: show exception in format as they were requested in rails 5 3 | tip-number: 21 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: In rails when an exception occurs, we throw the response in html format and with this feature added the error will be thrown in the format of which the request was made. 7 | 8 | --- 9 | 10 | Rails 5 has introduced new configuration to respond with proper format for exceptions. 11 | 12 | ```ruby 13 | # config/environments/development.rb 14 | config.debug_exception_response_format = :api 15 | ``` 16 | 17 | Let’s see an example of the response received with this configuration. 18 | 19 | ```ruby 20 | $ curl localhost:3000/posts.json 21 | {"status":404,"error":"Not Found","exception":"#\u003cActionController::RoutingError: No route matches [GET] \"/posts.json\"\u003e","traces":{"Application Trace":[...],"Framework Trace":[...]}} 22 | ``` 23 | 24 | The status key will represnt HTTP status code and error key will represent the corresponding Rack HTTP status. 25 | 26 | exception will print the output of actual exception in inspect format. 27 | 28 | traces will contain application and framework traces similar to how they are displayed in HTML error page. 29 | 30 | By default, config.debug_exception_response_format is set to :api so as to render responses in the same format as requests. 31 | 32 | If you want the original behavior of renndering HTML pages, you can configure this option as follows. 33 | 34 | ```ruby 35 | # config/environments/development.rb 36 | config.debug_exception_response_format = :default 37 | ``` 38 | -------------------------------------------------------------------------------- /rails_tip/2016-03-04-rails_console_auto_complete.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rails console autocomplete to save time 3 | tip-number: 22 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: In rails, we use rails console to test and interact directly with models and such from the command line and when we do so we can use the below set of tips to improve efficiency. 7 | 8 | --- 9 | 10 | Rails console has autocompletion support, which I think would definitely save lot of time instead of typing in the commands everytime. 11 | 12 | Suppose you have a Picture model that you previously used in the console and now you want to use it to run a query. Start by typing Mov and then hit Tab: 13 | 14 | ```ruby 15 | >> Pic 16 | ``` 17 | 18 | There's only one possible completion in this case, so it's autocompleted to what you want: 19 | 20 | ```ruby 21 | >> Picture 22 | ``` 23 | 24 | Given the class, you now want to use the where method to run the query. Start by typing .w and then hit Tab: 25 | 26 | ```ruby 27 | >> Picture.w 28 | ``` 29 | 30 | There's more than one valid completion in this case, so nothing happens (you may hear a bell). Now hit Tab a second time and you'll get a list of valid completions: 31 | 32 | ```ruby 33 | >> Picture.w 34 | 35 | Picture.where 36 | Picture.with_scope 37 | Picture.with_exclusive_scope 38 | Picture.with_warnings 39 | Picture.with_options 40 | ``` 41 | 42 | You want the where method, so type the next character in the method name (h) and hit Tab yet again: 43 | 44 | ```ruby 45 | >> Picture.wh 46 | ``` 47 | 48 | Bingo. That narrows it down to only one possible completion, so it's expanded to what you want: 49 | 50 | ```ruby 51 | >> Picture.where 52 | ``` 53 | 54 | Autocompletion saves a lot of typing and remembering. When in doubt, just keep hitting the Tab key. It will autocomplete class names, method names, and any variable/object names within the scope of the console session. 55 | 56 | Getting the Value of the Last Expression 57 | I can't begin to tell you how many times this one has come in handy. Here's an all-too-familiar situation: I manage to correctly type a useful hunk of code into the console, such as this query: 58 | 59 | ```ruby 60 | >> Picture.where("total_likes >= ?", 1000).order(:name) 61 | ``` 62 | 63 | I immediately hit Enter and the query runs. Then I remember that I actually wanted to do something with the results, but failed to assign the results to a variable. At this point I could hit the up arrow key to recall that line of code and then edit it, but there's an easier way. 64 | 65 | The return value of the last expression is automatically stored in the special underscore (_) variable. To assign the query results to a pictures variable, for example, I can use: 66 | 67 | ```ruby 68 | >> pictures = _ 69 | ``` 70 | 71 | Then I can actually do something with the results, such as counting the number of pictures: 72 | 73 | ```ruby 74 | >> pictures.size 75 | => 5 76 | ``` 77 | 78 | Alternatively, I could have called the size method directly on the _ variable: 79 | 80 | ```ruby 81 | >> _.size 82 | => 5 83 | ``` 84 | 85 | It's important to keep in mind that _ always contains the value of the last expression. So at this point the value of _ has changed to be the result of calling size on the array of pictures: 86 | 87 | ```ruby 88 | >> _ 89 | => 5 90 | ``` 91 | 92 | Neat little trick, that one. 93 | -------------------------------------------------------------------------------- /rails_tip/2016-03-05-http_cache_forever_rails_5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rails 5 http_cache_forever 3 | tip-number: 23 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: When response does not change then we want browsers and proxies to cache it for a long time. Method http_cache_forever allows us to set response headers to tell broswers and proxies that response has not modified. 7 | 8 | --- 9 | 10 | 11 | Rails 5 allows to cache HTTP responses forever by introducting http_cache_forever method. 12 | 13 | Sometimes, we have static pages that never/rarely change. 14 | 15 | ```ruby 16 | # app/controllers/home_controller.rb 17 | class HomeController < ApplicationController 18 | def index 19 | render 20 | end 21 | end 22 | 23 | # app/views/home/index.html.erb 24 |

Welcome

25 | ``` 26 | 27 | Let’s see log for the above action. 28 | 29 | ```ruby 30 | Processing by HomeController#index as HTML 31 | Rendered home/index.html.erb within layouts/application (1.3ms) 32 | Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms) 33 | ``` 34 | 35 | And so on for every request for this action. 36 | 37 | There is no change in the response and still we are rendering same thing again and again and again. 38 | 39 | Rails 5 introduces http_cache_forever 40 | 41 | When response does not change then we want browsers and proxies to cache it for a long time. 42 | 43 | Method http_cache_forever allows us to set response headers to tell broswers and proxies that response has not modified. 44 | 45 | ```ruby 46 | # app/controllers/home_controller.rb 47 | class HomeController < ApplicationController 48 | def index 49 | http_cache_forever(public: true, version: 'v1') {} 50 | end 51 | end 52 | 53 | # OR 54 | class HomeController < ApplicationController 55 | def index 56 | http_cache_forever(public: true, version: 'v1') do 57 | render 58 | end 59 | end 60 | end 61 | 62 | 63 | # app/views/home/index.html.erb 64 |

Welcome

65 | ``` 66 | 67 | Now let’s look at the log for the modified code. 68 | 69 | When request is made for the first time. 70 | 71 | ```ruby 72 | Processing by HomeController#index as HTML 73 | Rendered home/index.html.erb within layouts/application (1.3ms) 74 | Completed 200 OK in 224ms (Views: 212.4ms | ActiveRecord: 0.0ms) 75 | ``` 76 | 77 | For consecutive requests for the same page 78 | 79 | ```ruby 80 | Processing by HomeController#index as HTML 81 | Completed 304 Not Modified in 2ms (ActiveRecord: 0.0ms) 82 | ``` 83 | 84 | On first hit, we serve the request normally but, then on each subsequent request cache is revalidated and a “304 Not Modified” response is sent to the browser. 85 | 86 | -------------------------------------------------------------------------------- /rails_tip/2016-03-06-filter_parameter_enhancements_rails_5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rails 5 parameter filter improvement 3 | tip-number: 24 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Rails makes it very easy to filter data like passwords, credit card information, auth keys etc and prevent it from appearing in log files for security reason. 7 | 8 | --- 9 | 10 | By adding following line in application.rb, we can filter senstive information. 11 | 12 | ```ruby 13 | config.filter_parameters += [:password] 14 | ``` 15 | 16 | Now the log file will show [FILTERED] instead of real password value. 17 | 18 | This replacement of password with [FILTERED] is done recursively. 19 | 20 | ```ruby 21 | {user_name: "john", password: "123"} 22 | {user: {name: "john", password: "123"}} 23 | {user: {auth: {id: "john", password: "123"}}} 24 | ``` 25 | 26 | In all the above cases, “123” would be replaced by “[FILTERED]”. 27 | 28 | Now think of a situation where we do not want to filter all the occurrence of a key. 29 | 30 | Here is an example. 31 | 32 | ```ruby 33 | {credit_card: {number: "123456789", code: "999"}} 34 | {user_preference: {color: {name: "Grey", code: "999999"}}} 35 | ``` 36 | 37 | We definitely want to filter [:credit_card][:code] but we want [:color][:code] to show up in the log file. 38 | 39 | This can be achieved in Rails 5. 40 | 41 | The application.rb changes from 42 | 43 | ```ruby 44 | config.filter_parameters += ["code"] 45 | ``` 46 | to 47 | ```ruby 48 | config.filter_parameters += ["credit_card.code"] 49 | ``` 50 | 51 | In this case so long as parent of code is credit_card Rails will filter the data. 52 | 53 | -------------------------------------------------------------------------------- /rails_tip/2016-03-07-Interaction_to_app_from_console.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interaction with app from rails console 3 | tip-number: 25 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We can interact with the app from console to imitate the real user action without a browser or server 7 | 8 | --- 9 | 10 | ### Issuing Requests Interactively 11 | 12 | The app object can also issue faux requests into your app, mimicing what a real user might do. We tend not to do this very often, but it can be quite useful for one-off interactions with the app from the console. The best part is that no browser or server is required. 13 | 14 | Here's a quick test drive to give you a feel for what's possible: 15 | 16 | ```ruby 17 | >> app.get "/movies" 18 | => 200 19 | 20 | >> app.get "/users/1" 21 | => 302 22 | 23 | >> app.response.redirect_url 24 | => "http://www.example.com/session/new" 25 | 26 | >> app.post "/session", email: 'fred@example.com', password: 'secret' 27 | => 302 28 | 29 | >> app.response.redirect_url 30 | => "http://www.example.com/users/1" 31 | 32 | >> app.session[:user_id] 33 | => 7 34 | ``` 35 | 36 | For more details on the methods you can call on the app object to issue requests, check out the ActionDispatch::Integration::RequestHelpers documentation. 37 | -------------------------------------------------------------------------------- /rails_tip/2016-03-08-Increase_productivity_with_few_tricks.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Increase productivity with few tricks 3 | tip-number: 26 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We often do some repetitive things that won’t seem like taking much time but it actually does and the following are some of the tricks that would reduce some time of that kind. 7 | 8 | --- 9 | 10 | ### Quickly search command line history 11 | 12 | When you use large commands with multiple arguments from terminal, it would be difficult to remember that. And we might google it again and instead we can make use of **Ctrl + r** 13 | 14 | Open your terminal and press **Ctrl + r**. Start typing the first few chars of the command that you recently used. It should start showing you commands that matches your command query. If there is more than one command that matches, press **Ctrl + r** repeatedly to cycle through the commands that match your query. Press **Ctrl + e** to select a particular option. 15 | 16 | You can also say **history** in the command line to a list of every command that you may have executed. 17 | 18 | ### Reduce backspace time 19 | 20 | When typing a really long command line piece that spans 4 lines. Only to realise that you made a mistake in the beginning of the line? Now if you don’t know the shortcuts, you would probably press the right arrow to go to the beginning of the line character by character. But the pros know better. They use shortcuts. These shortcuts will save you hours of time playing with the arrow and backspace keys. 21 | 22 | **Ctrl + k** - Deletes everything to the right of the cursor 23 | 24 | **Ctrl + w** - Deletes everything to the left of the cursor (one word at a time) 25 | 26 | **Ctrl + a** - Go to the beginning of the line 27 | 28 | **Ctrl + e** - Go to the end of the line 29 | 30 | 31 | ### Reload the console on the fly 32 | 33 | You try something in the console, it doesn’t work. You change your code and try again? Nope got to restart the console session first. Sure its fine in the beginning but it starts to be a drag after a while. You can avoid this problem most of the time by simply saying 34 | 35 | ```ruby 36 | reload! 37 | ``` 38 | 39 | It will reload your entire Rails application without you having to terminate the session. 40 | 41 | -------------------------------------------------------------------------------- /rails_tip/2016-03-09-rendering_partial_from_cache_faster.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Render partial from cache substantially faster 3 | tip-number: 27 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: We render partial and below is the method that explains briefly about how to render partial faster. 7 | 8 | --- 9 | 10 | Let’s have a look at Rails view code that renders partial using a collection. 11 | 12 | ```ruby 13 | # index.html.erb 14 | <%= render partial: 'todo', collection: @todos %> 15 | 16 | # _todo.html.erb 17 | <% cache todo do %> 18 | <%= todo.name %> 19 | <% end %> 20 | ``` 21 | 22 | In the above case Rails will do one fetch from the cache for each todo. 23 | 24 | Fetch is usually pretty fast with any caching solution, however, one fetch per todo can make the app slow. 25 | 26 | Gem multi_fetch_fragments fixed this issue by using read_multi api provided by Rails. 27 | 28 | In a single call to cache, this gem fetches all the cache fragments for a collection. The author of the gem saw 78% speed improvement by using this gem. 29 | 30 | The features of this gem have been folded into Rails 5. 31 | 32 | To get benefits of collection caching, just add cached: true as shown below. 33 | 34 | ```ruby 35 | # index.html.erb 36 | <%= render partial: 'todo', collection: @todos, cached: true %> 37 | 38 | # _todo.html.erb 39 | <% cache todo do %> 40 | <%= todo.name %> 41 | <% end %> 42 | ``` 43 | 44 | With cached: true present, Rails will use read_multi to the cache store instead of reading from it every partial. 45 | 46 | Rails will also log cache hits in the logs as below. 47 | 48 | ```ruby 49 | Rendered collection of todos/_todo.html.erb [100 / 100 cache hits] (339.5ms) 50 | ``` 51 | -------------------------------------------------------------------------------- /rails_tip/2016-03-10-left_outer_join_in_Rails_5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Support for left outer join in Rails 5 3 | tip-number: 28 4 | tip-username: Logesh 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: In rails whenever we were supposed to use left outer join, we use raw sql instead of active record way and rails 5 has provided support to left outer join in active record way 7 | 8 | --- 9 | 10 | In Rails 4.x, we need to write the SQL for left outer join manually as Active Record does not have support for outer joins. 11 | 12 | ```ruby 13 | authors = Author.join('LEFT OUTER JOIN "posts" ON "posts"."author_id" = "authors"."id"') 14 | .uniq 15 | .select("authors.*, COUNT(posts.*) as posts_count") 16 | .group("authors.id") 17 | ``` 18 | 19 | Rails 5 has added left_outer_joins method. 20 | 21 | ```ruby 22 | authors = Author.left_outer_joins(:posts) 23 | .uniq 24 | .select("authors.*, COUNT(posts.*) as posts_count") 25 | .group("authors.id") 26 | ``` 27 | 28 | It also allows to perform the left join on multiple tables at the same time. 29 | 30 | ```ruby 31 | >> Author.left_joins :posts, :comments 32 | Author Load (0.1ms) SELECT "authors".* FROM "authors" LEFT OUTER JOIN "posts" ON "posts"."author_id" = "authors"."id" LEFT OUTER JOIN "comments" ON "comments"."author_id" = "authors"."id" 33 | ``` 34 | 35 | If you feel left_outer_joins is too long to type, then Rails 5 also has an alias method left_joins. 36 | -------------------------------------------------------------------------------- /rails_tip/2016-03-29-Retrieving ids.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Retriving the ids of the has_many or has_many_through relationships 3 | tip-number: 29 4 | tip-username: Bala Karthik 5 | tip-username-profile: https://github.com/balakarthik2011 6 | tip-description: Retriving the ids of the has_many or has_many_through relationships 7 | 8 | --- 9 | 10 | 11 | 12 | 13 | For example if You have two models post and comments 14 | 15 | post has many comments 16 | 17 | comments belongs to post 18 | 19 | if you want to retrive the ids of the comment of a particular post. 20 | 21 | you can use, 22 | 23 | ```ruby 24 | 25 | comments = Post.find(id).comment_ids 26 | ``` 27 | 28 | This is efficient when compared to using functions like map,pluck. 29 | 30 | 31 | ```ruby 32 | >> Post.first.comments.map(&:id) 33 | Post Load (1.0ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1 34 | Comment Load (3.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 1]] 35 | [1,4,6] 36 | ``` 37 | 38 | 39 | ```ruby 40 | >> Post.first.comments.pluck(:id) 41 | Post Load (1.5ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1 42 | (1.2ms) SELECT "comments"."id" FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 1]] 43 | [1,4,6] 44 | 45 | ``` 46 | 47 | 48 | ```ruby 49 | Post.first.comment_ids 50 | Post Load (1.0ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT 1 51 | (1.0ms) SELECT "comments".id FROM "comments" WHERE "comments"."post_id" = $1 [["post_id", 1]] 52 | [1,4,6] 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /tip_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: *Demo tip 3 | tip-number: 01 4 | tip-username: Test name 5 | tip-username-profile: https://github.com/logeshmallow 6 | tip-description: Test 7 | 8 | --- 9 | 10 | content here 11 | ### Subtitles format 12 | --------------------------------------------------------------------------------