RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

@rbates: one snag that I usually run into with facebook is exchanging access tokens when they expire. How do you prefer to deal with this?

Avatar

I've seen a lot of confusion about the various initialization files for shells. So I wanted to share the Startup Files page from zsh.sourceforget.net:

There are five startup files that zsh will read commands from:

$ZDOTDIR/.zshenv
$ZDOTDIR/.zprofile
$ZDOTDIR/.zshrc
$ZDOTDIR/.zlogin
$ZDOTDIR/.zlogout

If ZDOTDIR is not set, then the value of HOME is used; this is the usual case.

.zshenv is sourced on all invocations of the shell, unless the -f option is set. It should contain commands to set the command search path, plus other important environment variables. .zshenv should not contain commands that produce output or assume the shell is attached to a tty.

.zshrc is sourced in interactive shells. It should contain commands to set up aliases, functions, options, key bindings, etc.

.zlogin is sourced in login shells. It should contain commands that should be executed only in login shells.

.zlogout is sourced when login shells exit.

.zprofile is similar to .zlogin, except that it is sourced before .zshrc. .zprofile is meant as an alternative to .zlogin for ksh fans; the two are not intended to be used together, although this could certainly be done if desired.

.zlogin is not the place for alias definitions, options, environment variable settings, etc.; as a general rule, it should not change the shell environment at all. Rather, it should be used to set the terminal type and run a series of external commands (fortune, msgs, etc).

Avatar

+1

acts_as_xlsx is also a very quick way to get up and running with rails.

grab me on #axlsx if you have any questions.

Avatar

how do i use optimistic locking for a model with has_many :others and belongs_to :model, :touch => true?

Avatar

How can i create an initial User ? If i try to create the initial User I get SQLite3::SQLException: no such column: users.invitation_id: SELECT 1 AS one FROM "users" WHERE "users"."invitation_id" IS NULL LIMIT 1 .. SO first User does not need an invitation how can i make an exception?

Avatar

Mr. Bates, thank you!
I thought that I need some heavy gem to be able to generate medium complex XLS files. I am so glad you showed me wrong, I am up and running without any additional dependency. Btw. you could post a link to that XML reference you mentioned in Show Notes:
http://msdn.microsoft.com/en-us/library/aa140066%28v=office.10%29

Avatar

I needed a simple, straightforward way of exporting AR collections to excel, and I ended up doing the to_xls gem.

Avatar

Thanks for the great episode as usual!
By the way, if we use passenger standalone instead of the default rails server, it will run the app in a multi-threaded environment. That can be a quick way to test something in development without the need to rely on background tasks.

Avatar

If you don't use notification services like growl, put 'notification :off' at top of your Guardfile, and you won't see that notice when tests start up.

Avatar

I've dealt with the same issue on titanium appcelerator mobile platfom. We need a high security in our app, that's why we cannot apply password authorization type. So I have set redirect uri to localhost and I've extracted grant code directly from redirect URL. You can check https://github.com/OrganisedMinds/titanium-oauth2-client for your inspiration, but be aware - this is still in development. Anyway there are already some oauth 2.0 libraries from google developers written in java if you consider to native android development.

Avatar

Thanks a lot!
For a pro episode about XLS you can maybe try https://github.com/randym/axlsx
Really useful for advanced excel usage.

Avatar

Anyone know the key differences between jasminerice and evergreen?

Avatar

so... is it just me or did anyone else see subliminal message flashing at about 6:25?

Avatar

I have a brand new MBP with the most memory it can hold and for some reason lucid32 on vagrant is very very slow to forward the port.

Avatar

I managed to get rid of the redirect loop mentioned, and make the routing a bit more robust and friendly-forwarding-ish, by doing the following (I used this example when I attempted to internationalize the Rails Tutorial:

config/routes.rb

ruby
SampleApp::Application.routes.draw do
  scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
    # ...
    match '/about',   to: 'static_pages#about'
    # ...

    # handles /valid-locale
    root to: 'static_pages#home', as: "locale_root"
    # handles /valid-locale/fake-path
    match '*path', to: redirect { |params, request| "/#{params[:locale]}" }
  end

  # handles /
  root to: redirect("/#{I18n.default_locale}")
  # handles /bad-locale|anything/valid-path
  match '/*locale/*path', to: redirect("/#{I18n.default_locale}/%{path}")
  # handles /anything|valid-path-but-no-locale
  match '/*path', to: redirect("/#{I18n.default_locale}/%{path}")
end

Since there are two root_paths, I renamed the one inside the :locale scope so there would be no conflicts in the app and tests. I tested the routes using RSpec as follows:

spec/routing/routing_spec.rb

ruby
require 'spec_helper'

describe "Routes" do

  describe "locale scoped paths" do
    I18n.available_locales.each do |locale|

      describe "routing" do
        it "should route /:locale to the root path" do
          get("/#{locale.to_s}").
            should route_to("static_pages#home", locale: locale.to_s)
        end
      end

      describe "redirecting", type: :request do

        subject { response }

        context "fake paths" do
          let(:fake_path) { "fake_path" }

          before { get "/#{locale.to_s}/#{fake_path}" }
          it { should redirect_to(locale_root_path(locale)) }
        end
      end

    end
  end

  describe "non-locale scoped paths" do

    describe "redirecting", type: :request do

      subject { response }

      context "no path given" do
        before { get "/" }
        it { should redirect_to(locale_root_path(I18n.default_locale)) }
      end

      context "a valid action" do
        let(:action) { "about" }
        let!(:default_locale_action_path) { about_path(I18n.default_locale) }

        context "with a valid but unsupported locale" do
          let(:unsupported_locale) { "fr" }

          before { get "/#{unsupported_locale}/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end

        context "with invalid information for the locale" do
          let(:invalid_locale) { "invalid" }

          before { get "/#{invalid_locale}/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end

        context "with no locale information" do
          before { get "/#{action}" }
          it { should redirect_to(default_locale_action_path) }
        end
      end

      context "invalid information" do
        let(:invalid_info) { "invalid" }

        before { get "/#{invalid_info}" }
        it { should redirect_to("/#{I18n.default_locale}/#{invalid_info}") }
        # This will then get caught by the "redirecting fake paths" condition
        # and hence be redirected to locale_root_path with I18n.default_locale
      end
    end
  end
end

I know that redirects are technically requests and their tests should really be under the spec/requests/ directory, but I figured they'd be more appropriate under routing since they're really just tests for exceptions and catch-alls. Anyway, hope this helps or is of interest to someone.

Avatar

If your fixture form's input had the same id (#order_card_number) then you could include order.js.coffee in the spec. But this is probably a bad idea as the tests lose isolation and it's not really a substitute for a full acceptance test with capybara/selenium.

Avatar

You can refer to it as @Mine in the local scope.

Avatar

UPDATE: deployed the test app on Heroku and everything works so I guess it is some facebook domain issue. Still no go for localhost.

Avatar

Great tutorial. Any example on config Sunspot for polymorphic associations?

Avatar

I followed the screencast step by step and couldn't get the login redirection working.
After approving the app with FB's dialog, i'm being redirected to a permissions request dialog and then all I get is a blank page as seen in the screenshot:

the contents of the dialog is the following javascript snippet

html
<script type="text/javascript">
var message = "cb=f3f46734&origin=http\u00253A\u00252F\u00252Flocalhost\u00253A3000\u00252Fffa487e6c&domain=localhost&relation=opener&frame=f251e19854&access_token=AAACsO0WgThwBAOjbW8ItSOhsHvPFhrzegH2tIVMZCmIgyYkObv1qeD23DVEMsP6Co7ENGBiKEFICEPZBHnzwNO9cbpRoilq9YpLKcuJAZDZD&expires_in=5110&signed_request=doBGkVVmt5I-FsXsL2Wy76SPTHgxftRpEy2yjS_nePs.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvZGUiOiJBUUIxWnlwWVI2X1VaQzE2TmJqdnB3VHk3dzZSc0pHY3NVVHhRNWZJR2NmWGxZRUZoLVpOQTQ5ekpBc1FlLWpjVlhXdDl3RzRDWmU0U2d2RnVtcDdmdDUzbWNuWDNzcUdKZlU5WWVKQkg2TzJDb3dKTTBrTjFtU1F6N1pXOENBSEZwVENnaWVZbUg2UndyY28yT1dJaFk4TFZqQmg4QTRkdDVJUDNJUFM3MmppMkFkb3RpenVHb0R6NnJJVzE2eFh4QUUiLCJpc3N1ZWRfYXQiOjEzNDEwNDUyOTAsInVzZXJfaWQiOiI4ODM5MzUwMjIifQ&base_domain=localhost", origin = "http:\/\/localhost:3000\/ffa487e6c", domain = "localhost";document.domain='facebook.com';(function(){var a=window.opener||window.parent,b='fb_xdm_frame_'+location.protocol.replace(':','');function c(){try{a.frames[b].proxyMessage(message,[domain]);}catch(e){setTimeout(c,100);}}function d(){__fbNative.postMessage(message,origin);}if(window===top&&/FBAN\/\w+;/i.test(navigator.userAgent)){if(window.__fbNative&&__fbNative.postMessage){d();}else window.addEventListener('fbNativeReady',d);}else c();})();

</script>

I'm suspecting Facebook's strict policies with XSS and same-site origin requests but it worked for Ryan...

Maybe one of you wonderful readers have bumped into this "undebuggable" weird behavior?

Avatar

I have used this with my meal planner app. I have it working but wonder, as above user. Can you add additional data? Example

I have it working to add ingredients to a meal. How could I specify the quantity of each ingredient? I am experimenting with the onAdd method, any help would be appreciated.

Avatar

You can show the AMOUNT the user is going to PAY by fetching the TOTAL PRICE on the CART in Orders#new

Avatar

How can this be used on a create action to keep the user on the same page? Any ideas?

Avatar

Why is underscore version staying in 1.3.1?

I am using the backbone-on-rails gem and having some issues that seem to be related to the fact that in my app underscore is stuck at version 1.3.1 when 1.3.3 is latest. My gemfile version is 0.9.2.0 for backbone-on-rails which has the latest underscore. I know this must be something basic – but I would think that the underscore file should automatically be updated to 1.3.3 by using this gem no? Anyone have any ideas why it would stay at 1.3.1?

Avatar

Has anyone figured out a way to load the authorization dialog in a modal window rather than a popup? From what I can tell, this currently isn't possible.

Avatar

Ryan,

So am I right in thinking that I have to invoke the methods that would otherwise have been called on page load? That is, we cannot rely upon DOM events firing for our fixtures? Integration testing is where you would want to test that (or call the function manually in the Jasmine test)?

Avatar

Hi,

that was one thing I didn't get - I was missing the action in the application controller.
However, you shouldn't use render here - you limit yourself. The way Ryan is doing it here gives you the opportunity to "overwrite" the template by putting another version of the template into the specific controllers view directory.

Avatar

I was having this issue and that line was exactly what I was missing. Thank you so much.

Flaviu
@closedbracket

Avatar

Very useful. Thanks, Ryan.

I did have to change a few things before it worked in Rails 3.0 though. I had to remove the html hash in the delete form.

delete.html.erb
<%= form_tag request.url, method: :delete do %>

And I needed to add a delete method to the application_controller:

application_controller.rb
  def delete
    render 'application/delete'
  end

After that it worked beautifully.

Avatar

Regarding the difference between

coffeescript
class Mine

@Mine = Mine

and

coffeescript
class @Mine

seems to be local only, that is, that the implicit declaration will not expose Mine in the local scope, which might be a pitfall
at first.

Avatar

I figured this out. I posted an answer to my own question - see if this helps:http://stackoverflow.com/questions/11240756/facebook-authentication-with-devise-omniauth-facebook-not-doing-anything/11256425#11256425

Basically, I forgot to add it to the attr_accessible on the User model, and I also had to unchange the changes I made to the after_sign_in_path_for method that devise comes along with. And also, dont forget to create a migration to add the columns provider and uid to the user table.

Avatar

I had issues installing Postgres with the instructions in this Railscast. However I was able to get postgres running on my project with http://postgresapp.com/ and http://inductionapp.com/ (Hat tip to this stackoverflow thread).

  1. Download & install Postgres.app (documentation) Make sure to install in /Applications.
  2. Update your PATH
    In my case I added the following to ~/.bash_profile
    export PATH="/Applications/Postgres.app/Contents/MacOS/bin:$PATH"
    Check that Postgres.app is being loaded
$ which psql
/Applications/Postgres.app/Contents/MacOS/bin/psql
  1. Update /config/database.yml
development:
     adapter: postgresql
     encoding: unicode
     database: myapp_development
     pool: 5
     host: localhost
  1. bundle exec rake db:create:all
  2. I'm hosting my app on Heroku so then ran a heroku db:pull
  3. Download & install Induction.
  4. Launch Induction and connect using these settings.
    NOTE Select the last postgres option in Adapter dropdown
Adapter     postgres
Hostname    localhost
Username    [I left this blank]
Password    [I left this blank]
Port        5432
Database    [I left this blank]
  1. Once Induction launches you can select your app's database from list in top left dropdown.
Avatar

Could it be due to CoffeeScript space vs. tab?

Avatar

Does your config/application.rb file have this?

config.assets.initialize_on_precompile = false

Avatar

How would I change the templates to use Handlebars? I've tried using 'handlebars_assets'. But I'm getting odd errors. Any chances to see versions of /templates/entries/entry.jst.hbs and index.jst.hbs?

Avatar

To 2.1.0 or to master? I still see the issue with master on Heroku as of today (it's been like that for a week).

Avatar

You can pass a :display =>"popup", to open the omniauth dialog in a popup:

ruby
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET'], :display => "popup"

It's a similar experience to the Javascript SDK when combined with the code from:

Turn omniauth facebook login into a popup (StackOverflow)

Avatar

I think you can have a simple locale flag before calling auth/twitter. Something like this:

Rails.application.config.middleware.use OmniAuth::Builder do
case current_locale
when 'en'
provider :twitter, 'app1-key', 'app1-secret'
when 'es'
provider :twitter, 'app2-key', 'app2-secret'
else
provider :twitter, 'app3-key', 'app3-secret'
end
end

Avatar

Does anyone know if the uid returned by the provider remains constant all the time? Can it be treated like a primary key for the user,provider combination?

Avatar

+1. I am also looking forward to the revised devise with omniauth.

Avatar

Nice episode!

I have issues trying to test blocking input into a text field. I made a jQuery plugin that forbids inputing number, spaces, or chars, but since triggering keypress, keyup or keydown dont actually print the value into the text field (it trigger the event but does not puts a value there) i have no way of making the correct expectation (not even with the sendkeys plugin).

Anyone knows how to test this kind of things?

Avatar

I like to wrap my classes on a global namespace such as:

coffeescript
@App = new Object

And then:

coffeescript
class App.CreditCard
Avatar

I just updated the twitter-bootstrap-rails gem and it worked.

Avatar

When testing manually what is the best way of avoiding the dependency on Facebook?

Avatar

Hello guys,
do you know how to do it with one drop down menu and hidden check boxes? When you click on "Yes" in drop down menu, it will display check boxes underneath but if you click on "never" it will not display anything underneath. Thank you

Avatar

When I selecting the are to crop, the selected area always be zoomed a bit. How can I fix this? I don't want the zoom effect.