RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

For CSV files, I was able to set the send_data type param as "text/csv". For the XLS xlm schema approach, are you all getting the file downloaded to have the .xls extension? My filename is just the name of the view, without extension.

Thanks

Avatar

I had the same perennial desire to be able to add images to a gallery without having to save it first.

I found a sample app demo of jquery-file-upload using carrierwave on GitHub that did almost what I wanted. I added the ability to be able to add images before the gallery record had been saved.

I generated a unique token (GUID) when a "New Gallery" form is displayed. This token is saved with each image as it's uploaded and saved as an independent "Picture" record. When the gallery is finally saved, it finds any Picture records with the matching token, and adds them as children.

Note: if you upload images, but abandon the form before saving it, you do get orphaned pictures. You would need to clean these up periodically.

https://github.com/dlehman/Rails-Carrierwave-jQuery-File-Upload

Avatar

In Ryan's example, storing the data in the DOM and also retrieving it using AJAX, it would incur multiple database calls. But Ryan was simply demonstrating how you could use the serializers to store data in the DOM. In the real world, you likely wouldn't need both on the same page.

Avatar

Sorry for sounding obtuse, but does that solve the issue with nested properties?

Avatar

I'd loved to see a revised version of this!

Avatar

How to configure Torquebox for https connection? I have tried as per document. When i send request though web brower , it not accepting http connection.

Avatar

Thanks for the Ember series, Ryan. ExtJS has taught me how NOT to do SPAs, now I'm looking for ways to do them right. Will there be, or could there be, an Ember Part 3 episode covering validation, error handling, and testing?

Avatar

Hi,

I tried your approach but with a variation. It doesn't work for me. Can you please check out the description of this problem?

http://stackoverflow.com/questions/15511820/activerecord-reputation-system-gem-extra-functionality-implementation

Avatar

I am pretty new to json api's and have a beginner question. So in this video Ryan put's the json data in an html data attribute as opposed to using an ajax request to get the json data.

So let's say I have a respond_to block for html and json. When the page loads I make an ajax get request to load the data from the server. If I use a get request to retrieve the data, am I really making 2 calls to the database? The first triggered by the html format of the index action and the 2nd triggered by the get request?

Avatar

I want to change the heading of calendar as: Sun, Mon and so on. what is the idea?

Avatar

Yes, I also find js-episodes quite boring and distracting from the Rails theme

Avatar

JS frameworks interact identically with all server-side frameworks. Rails integration process is tivial and is not worth half of all last month's episodes

Avatar

Rails gurus should probably have a pretty good idea how client side js frameworks work with Rails.

Avatar

Railscasts make me more and more sad lately: boring reviews of monstrous js-frameworks instead of hardcore rails features.

Had I wanted to be js-guru I would have subscribed to something js-oriented, not rails.

It's time to be renamed to jscasts. Waiting for node.js reviews as a part of digging inside trash process.

Avatar

I also needed to manually call html: {enctype: "multipart/form-data"} in my form_tag. Once I wasn't calling a file_field the enctype was no longer being set as multipart.

Avatar

Same for me, although not even limited to Rails 4. I'm running 3.2.13 and getting the same problem.

Avatar

Hi everyone and thank you Ryan for this great screencast

I have an issue with the password reset edit form. The reset url is correctly generate and I can access the form, but my update action doesn't seem to work. Actually, I can send my form with empty fields for "password" and "password confirmation" and it will still trigger the "Password has been reset!" notice.

It looks as though my user validations aren't being taken into account here.

I tried adding both password and password confirmation validation to my User model:

ruby
validates :username, :email, :password, :password_confirmation, :presence => true

which is weird because when creating a new user, I didn't need those validations (the has_secure_password feature seemed to implement these validations), but the edit reset password form seems to need them.

Anyway, my edit_password_reset form worked, but it broke my new_password_reset form because it required both non blank password and password confirmation.

What am I missing here?

Avatar

I tried to decouple the receiving of a ticket from the further processing using observers.

For that I added an observer to tickets:

ruby
class TicketObserver < ActiveRecord::Observer
  def after_create(ticket)
   puts ticket.from
        end
end

This works fine when adding a new ticket through the browser. However when I send an email to my application I'll get the following exception:

E, [2013-03-19T20:19:50.352625 #8296] ERROR -- : uninitialized constant Ticket
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/inflector/methods.rb:230:in block in constantize'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/inflector/methods.rb:229:in
each'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/inflector/methods.rb:229:in constantize'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/core_ext/string/inflections.rb:54:in
constantize'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:210:in observed_class'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:203:in
observed_classes'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:223:in observed_classes'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.12/lib/active_record/observer.rb:96:in
observed_classes'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:219:in initialize'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/singleton.rb:141:in
new'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/singleton.rb:141:in block in instance'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/singleton.rb:139:in
synchronize'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/singleton.rb:139:in instance'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:86:in
instantiate_observer'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:59:in block in instantiate_observers'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:59:in
each'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.12/lib/active_model/observing.rb:59:in instantiate_observers'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.12/lib/active_record/railtie.rb:117:in
block (2 levels) in class:Railtie'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/lazy_load_hooks.rb:36:in instance_eval'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/lazy_load_hooks.rb:36:in
execute_hook'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/lazy_load_hooks.rb:43:in block in run_load_hooks'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/lazy_load_hooks.rb:42:in
each'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.12/lib/active_support/lazy_load_hooks.rb:42:in run_load_hooks'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.12/lib/active_record/base.rb:720:in
'
/Users/tummam/Documents/Rails/ticketing/app/models/ticket.rb:1:in <top (required)>'
script/mailman_server:19:in
block (2 levels) in '
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/router.rb:66:in instance_exec'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/router.rb:66:in
route'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/message_processor.rb:19:in process'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/receiver/pop3.rb:41:in
block in get_messages'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/net/pop.rb:665:in each'
/Users/tummam/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/net/pop.rb:665:in
each_mail'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/receiver/pop3.rb:40:in get_messages'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/application.rb:118:in
block in polling_loop'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/application.rb:115:in loop'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/application.rb:115:in
polling_loop'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/application.rb:75:in run'
/Users/tummam/.rvm/gems/ruby-2.0.0-p0/gems/mailman-0.6.0/lib/mailman/application.rb:7:in
run'
script/mailman_server:16:in `'
To me it looks like the observer is the wrong idea to handle further processing. However as I envision it to be rather complex I wanted to decouple it from the receiving part of the application.

Can someone help me out with the observer problem or suggest a better method to do it?

Avatar

Ryan shows very nice how to integrate js-frameworks into Rails. Thats very helpful.

Avatar

ApplicationController#present is not used in profile-after. It could be safely commented out.

Am I right?

Avatar

Railscasts make me more and more sad lately: boring js-frameworks reviews instead of hardcore rails features.

It's time for be renamed to jscasts.

Avatar

One source of errors at my end was an assumption that card values (number, expiration, CVC) that passed a token request (returned 200):

.js
      return Stripe.createToken(card, order.handleStripeResponse);

would necessarily be a valid card token for:

.rb
      customer = Stripe::Customer.create(card: stripe_card_token, description: email)

This is NOT the case. Stripe.createToken does very minimal checking of the card values. From Stripe, all it is doing is making sure the card number is long ENOUGH (not the right length) and passes the Luhn test. Adding extra digits to the card can result in a 200 response, even though the card number is not valid. Stripe.createToken only checks that the expiration date is in the future, not that it is the correct date associated with the card.

It is not UNTIL Customer.create that the card is actually determined to be a real, valid card. Therefore, Customer.create can fail with what Stripe has provided as a valid card token.

Try, for instance, what happens if you use card number:

4242 4242 4242 4242 42

rather than:

4242 4242 4242 4242

Avatar

I fixed this by changing created_at in the select clause to date(created_at). In my case, I also needed to add unscoped. before the where clause in order to eliminate my model's default ordering by name, which PG also complained about for the same reason, and I added a order('date(created_at)') for good measure.

Here's the edited code that works in PostgreSQL:

ruby
users = unscoped.where(created_at: start.beginning_of_day..Time.zone.now)
users = users.group('date(created_at)')
users = users.order('date(created_at)')
users = users.select('date(created_at) as created_at, count(*) as count')
users.each_with_object({}) do |user, counts|
        counts[user.created_at.to_date] = user.count
end
Avatar

You can also go with Slim which does not have the problems Haml has with interpolation of Handlebar templates. Stuff is still rendered on the server side then.

Avatar

Great episode as always.

The only suggestion I have is to include testing in all new episodes, it would add a lot of value to your screencasts and I know new developers like myself would appreciate it. Hell even if you don't cover the tests in the screencast but include them in the source code I would learn something.

Avatar

I have a feeling such operations should be refactored into a separate model (e.g. BulkProductsUpdater), this has several advantages:

  1. You won't need any non-REST actions for this new object
  2. You can utilize handy rails validations/callbacks
  3. All the business logic related to updating the Product fields will be contained in the model layer, as it should be
  4. Generally testing separate models is easier and less brittle than testing controller logic
Avatar

This way you can save a request to server by just reading the data included in DOM.

Avatar

Ryan, I hope you like Backbone best :), and use it instead of the others if you go deeper into these frameworks, which I also hope you do--rather than continuing to introduce new ones.

Having seen your coverage of Backbone, Angular, Ember etc, I'd feel pretty confident about learning batman.js on my own, for example, if I felt there was a need, and I assume it'd be similar for other subscribers. However, I'd really like to see you go deeper into how Backbone and Rails can be used together. Just my two cents.

Avatar

You may use this approach to store data (here a whole JSON object) that will be used / processed through Javascript client-side.

Avatar

Over a year later and it works. Thank you :)

Avatar

I adapted Ryan's example to the code below, which works just fine on SQLite. However, on PostgreSQL (Heroku), I get the error

PGError: ERROR: column "users.created_at" must appear in the GROUP BY clause or be used in an aggregate function

Any ideas on making this work in PostgreSQL?

Here's the relevant code:

ruby
users = where(created_at: start.beginning_of_day..Time.zone.now)
users = users.group('date(created_at)')
users = users.select('created_at, count(*) as count')
users.each_with_object({}) do |user, counts|
        counts[user.created_at.to_date] = user.count
end
Avatar

Thanks for the tip. I'm also interested in parsing tens of thousands of lines of excel data in rails.

Could you say more about how you set up Gnumeric/ssconvert on your production server? We're running Ubuntu 12 and I'm not seeing an obvious way to get the command-line ssconvert program installed without installing Gnumeric and all of the Gnome packages it depends on.

Avatar

It doesn't appear that include PublicActivity::Common works in the current release of the gem, so not sure how this appeared to work in the episode without using a pre-release version of the gem.

See https://github.com/pokonski/public_activity/issues/62 for workarounds.

Avatar

Have you found a solution to this problem ?

Avatar

Ryan what would you choose between BackboneJS, Ember or Angular ? I really like Angular.. what do you think ?

Avatar

@rbates
If I have a custom font how do I load that into the rails app.
@font-face is used in pure html for fetching the font face.
This can be useful for people working on premium apps with their own fonts.

Avatar

I'm getting this weird errror: "NameError (uninitialized constant ReportsController::ReportsDatatable):
app/controllers/reports_controller.rb:20:in `block (2 levels) in index'"

The weird thing is sometimes when I load the table I get this error, but other times I do not. Also everytime I try to go to the next page this error occurs.

Any ideas?

Avatar

How to have only active announcement ids in the cookies.signed[:hidden_announcement_ids]

This is kind of 'amateur hour' code (my specialty), but:

After using site-wide-announcements for several months, the development log was passing several dozen expired ids on each page load:

SELECT "announcements".* 
  FROM "announcements" 
  WHERE (starts_at <= '2013-03-18 06:55:20.343948' and ends_at >= '2013-03-18 06:55:20.343948') 
  AND (id not in (10,9,23,45,32,12,6,7,8,76,4,8,90,5,43,2,67,54,3,2,6,5,67,89,2,8,9,7,54,6,7,32,24,56,77,7,53,2,1)) 
  ORDER BY id desc

I got tired of looking at all those ids, so as a test I tried to figure out how to have only active announcement ids in the cookies.signed[:hidden_announcement_ids].

Deleting the cookie was simple, but would re-display previously hidden announcements.

Here's my solution.

An 'active' name scope (id in (?)), as opposed to the 'current' scope (id not in (?))

models/announcement.rb
  def self.active(hidden_ids = nil)
    result = where("starts_at <= :now and ends_at >= :now", now: Time.zone.now)
    result = result.where("id in (?)", hidden_ids) if hidden_ids.present?
    result
  end

An after_filter :flush_announcement_cookie, placed on the users' login landing dashboard_controller.

dashboard_controller
  after_filter :flush_announcement_cookie

  def flush_announcement_cookie
    if cookies.signed[:hidden_announcement_ids].present?      
      ids = Announcement.active(cookies.signed[:hidden_announcement_ids]).pluck(:id)
      cookies.permanent.signed[:hidden_announcement_ids] = ids
    end
  end

Hope this helps somebody.

Avatar

I'ved added raise omni = request.env["omniauth.auth"].to_yaml to the Authentication#create controller but when I authenticate with Twitter and it redirects back, I get:

TypeError: can't convert nil into String

and in the stack trace the first one of many is:
omniauth-twitter (0.0.14) lib/omniauth/strategies/twitter.rb:23:in `+'

In the url it displays the correct users/auth/twitter url with the oauth_token as parameters. I'm not sure what I'm doing wrong, does anyone know what to try to fix this?

Avatar

I downloaded and tried example, background doesn't work, how can I set background-color when I use the dark background theme? thanks.

Avatar

does angularjs-rails-resource replace angularjs-rails or can it be used in addition to it?

I may have answered my own question because I noticed that angularjs-rails-resource only contains resource.js whereas angularjs-rails has bootstrap related files etc -

So I would say both

Avatar

'#each' feels a lot like ruby. e.g. array.each { |x| puts x }

Pretty sure that's by design. Made me smile when I saw that in ember.

I think it's interesting how emotional people get about frameworks, guess it's a matter of not wanting to waste your time learning something that may or may not be useful in the end. I know I've spent a lot of time learning ember, this better be the next big thing! :)

Avatar

After adding the gem 'devise_rpx_connectable', I ran into the same error: 'require': cannot load such file -- devise/schema (LoadError). I got rid of the error by deleting the contents of the corresponding schema.rb and the migration command seemed to work again.

It seems that with the newer version (> 2.1) of devise, the contents of this file aren't necessary. Hope this solves other peoples issues, especially if they decide to update the devise gem and continue to use devise_rpx_connectable like I did.

Avatar

I love these, it helps me in finally understanding how you are supposed to use Rails instead of just following recommendations.