Routing rspec with nested routes

Problem

You would like to add a routing rspec test in your rails application that tests for a nested route.
So while you have something like the following in your config/routes.rb file:

namespace :admin do
  resources :users do
    resources :audits, only: [:index]
  end
end

you want to add the following test for your route:

expect(get: '/admin/users/:user_id/audits').to route_to(controller: 'admin/audits', action: 'index')

but you are getting an error like the following:

The recognized options <{"controller"=>"admin/audits", "action"=>"index", "user_id"=>":user_id"}> did not match <{"controller"=>"admin/audits", "action"=>"index"}>, difference:.
       --- expected
       +++ actual
       @@ -1 +1 @@
       -{"controller"=>"admin/audits", "action"=>"index"}
       +{"controller"=>"admin/audits", "action"=>"index", "user_id"=>":user_id"}

Solution

You will need to change your rspec to the following using any number for the user_id:

expect(get: '/admin/users/42/audits').to route_to(controller: 'admin/audits', action: 'index', user_id: '42')

Solution adapted from here

Upgrading jquery-ui-rails from 4.2.1 to 0.5.0

Problem

You would like to upgrade your jquery-ui-rails gem from a version before 0.5.x to the latest version 0.5.0, but when you do that your tests are failing with error messages similar to the one below:

ActionView::Template::Error: 
couldn't find file 'jquery.ui.effect-blind'

Solution

According to the changelog the naming between 4.2.1 and 0.5.0 has changed jquery-ui-rails

So if you were using something like the following in your app/assets/javascripts/applications.js file (as used in the depot example in the Agile Web Development with Rails 4 book):

//= require jquery.ui.effect-blind

you would need to change it to the following after upgrading your jquery-ui-rails gem to ~> 0.5.0:

//= require jquery-ui/effect-blind

Disabling SQL logging in rails development

Problem

You are working on a new feature that outputs a lot of SQL code in your log file so it’s difficult to see what else is happening, and you would like to disable the SQL logging in your development environment temporarily.

Solution

You can add the following to your config/application.rb file:

if Rails.env.development?
  ActiveRecord::Base.logger = Logger.new('/dev/null')
end

Thanks to the solution here

Apache rewrite rule to redirect https to http for pages you don’t need https

Problem

You are using your Rails 3.2.x application with Apache and you have setup force_ssl in one of your controllers (ie payments), that you want to force the application to use ssl. But after you set it up, and you go to one of the actions for that controller, every subsequent page you follow still uses the https protocol, even if you don’t want them to.
So you need a way to force the serving of pages in http.

Solution

You can use a redirection in your SSL apache conf file, and specify that when it doesn’t match the sections (controller,actions) you specify it should be redirected to http.
Note that RewriteCond in Apache are by default ANDed when they are in subsequent lines so you can add more conditions and that you can use [OR] if you want to perform an OR logic operation.
So by adding the following in your virtual host for the 443 port (ssl), and apply the changes it should be working as expected:

# Add https to http redirection
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/controller_you_want_ssl.*
RewriteRule (.*)  http://%{HTTP_HOST}%{REQUEST_URI}

Using named gemsets with rvm

Problem

You want to be able to use different gems/rails version for your application after installing the latest rails version, without having to use bundle exec.

 

Solution

You can use the named gemsets with rvm.

More instructions are here: http://beginrescueend.com/gemsets/basics/

so you can install two gemsets for example ruby-1.9.3-p0@rails3_0_11 and another with ruby-1.9.3-p0@rails3_2_1

you could then do :

rvm gemset create rails3_0_11 rails3_2_1

rvm 1.9.3-p0@rails3_0_11
gem install rails -v 3.0.11

rvm 1.9.3-p0@rails3_2_1
gem install rails -v 3.2.1

rvm gemset use rails3_0_11
bundle install

you could then also use some aliases in your ~/.bashrc file to be able to use the gemsets by using only one command as for example in ($ rvm3011):

# Rails 3.0.x
alias rvm3011="rvm gemset use rails3_0_11"
alias rvm3012="rvm gemset use rails3_0_12"

# Rails 3.2.x
alias rvm321="rvm gemset use rails3_2_1"
alias rvm322="rvm gemset use rails3_2_2"

setting dynamic event_source in jquery fullcalendar in rails application

Problem

You would like to use the fullcalendar jquery plugin to be able to display events in your rails application, but you also want to be able to set the eventSources dynamically depending on the path to your view, especially if your view contains a relationship as in the following example:

model_a/1/model_b (user/14/comments)

Solution

Change your eventSources to be something like the following and using the jQuery.ajaxSettings.url :

 // a future calendar might have many sources.
    eventSources: [{
      url: jQuery.ajaxSettings.url,
      color: 'orange',
      textColor: 'black',
      ignoreTimezone: false
    }],

 

ActiveSupport::TimeWithZone comparisons

Problem
You have two dates that you want to compare in your Rails application, which are both ActiveSupport::TimeWithZone.

Although they both look identical, when you are trying to compare them for equality (using ==), you get back false as a result.

 

Solution

These dates can have a difference in milliseconds that doesn’t normally get displayed. So first of all try to use to_f to see if they really have a difference.

If they do, then you would need to compare them by converting them to integers first as in :

date_a.to_i == date_b.to_i

and you should be getting back true

Rails find case sensitive search

Problem
You want to use find in Rails for a case sensitive search. For example in your authentication logic you have something to find the user to login as in:
u=User.find_by_login(‘username’)
If you don’t want to limit the available logins with case insensitive validation in the model, then the above code will not work if you have ‘Username’ and ‘username’ as available logins, as the find will only return one of them.

Solution
Change the find method to use the BINARY keyword in your database (only used with MySQL), as in the following:
u=User.find(:first, :conditions => [“BINARY login = ?”, login])