RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Bootstrap is a really effective, saved a lot of time in my teams development cycles :)

Just a quick note on less/sass/haml contra less/css/erb

Due to some issues getting team members to wrap their head around sass and haml we're using the following gems:

gem 'less', '2.0.9'
gem 'less-rails', '2.1.6'
gem 'less-rails-bootstrap', '2.0.6'

instead of

gem 'sass-rails'

Works great as well together with simple form.

Avatar

Any suggestions to avoid class="span3"? It seems like it would be a maintenance headache.

Docs:
"Use the same .span* classes from the grid system for input sizes."

Avatar

If you are using bootstrap-sass, and want to get will_paginate working flawlessly, add the following in an initializer (e.g. config/initializers/will_paginate.rb):

if defined?(WillPaginate)
  module WillPaginate
    module ActionView
      def will_paginate(collection = nil, options = {})
        options[:renderer] ||= BootstrapLinkRenderer
        super.try :html_safe
      end

      class BootstrapLinkRenderer < LinkRenderer
        protected

        def html_container(html)
          tag :div, tag(:ul, html), container_attributes
        end

        def page_number(page)
          tag :li, link(page, page, :rel => rel_value(page)), :class => ('active' if page == current_page)
        end

        def previous_or_next_page(page, text, classname)
          tag :li, link(text, page || '#'), :class => [classname[0..3], classname, ('disabled' unless page)].join(' ')
        end

        def gap
          tag :li, link(super, '#'), :class => 'disabled'
        end
      end
    end
  end
end
Avatar

If anyone else is using this combination, and need to create a "between" input (e.g. from date to date), it can be done with meta_search's between field (see how to add it in the meta_search docs), and add this input to Formtastic (/app/inputs/between_input.rb)

class BetweenInput < FormtasticBootstrap::Inputs::StringInput
  def to_html
    input_wrapping do
      label_html <<
      builder.multiparameter_field(method, {:field_type => options[:field_type]}, {:field_type => options[:field_type]}, input_html_options.except(:id))
    end
  end
end

(The .except :id is because Formtastic will othwise make both the between field's id's the same, which will mess up e.g. jQuery UI datepicker)

Avatar

Just to confirm that it is working: I am using the bootstrap-sass gem in a project right now with Bootstrap 2.0 and Formtastic 2.0 It works beautifully :-)

Avatar

Yes Ryan is right. Anything before IE 9 is an older version of erm, any web browser?

Avatar

If you want a small solution for generating the form markup, I've created a gem called bootstrap_forms, which eliminates the need for all the messy markup bootstrap requires.

https://github.com/sethvargo/bootstrap_forms

Avatar

Here's a useful jquery snippet for anyone looking to do jquery powered transitions on their PJAX calls:

Simple slide down

javascript
//jQuery =>
$('#PJAXcontainer').bind('start.pjax', function() { $('#PJAXcontainer').hide() }).bind('end.pjax', function() { $('#PJAXcontainer').slideDown(250) });

could also be used for Fades, etc.

javascript
// jQuery =>
$('#PJAXcontainer').bind('start.pjax', function() { $('#PJAXcontainer').fadeOut(500) }).bind('end.pjax', function() { $('#PJAXcontainer').fadeIn(500) });

Should go without saying to use it in $(document).ready function, or similar.

Avatar

I would really like to see also email account confirmation implementation, Thanks Ryan!

Avatar

Anybody else getting:

undefined local variable or method `current_user'

I don't know why my helper method is not getting loaded..

Avatar

define in your gemfile that you need '0.6.0'. apparently they released a new version and somehow my gemfile thought it had to use 0.2.8. Which clearly wasn't compatible yet with rails 3.2.

Avatar

You should keep releasing this screencast like every few months!

BTW- Does anyone have any preferred methods or tools for creating flow of the different user states in a web app, for example, logged in, guest, etc..

Avatar

Please see this project on github:

https://github.com/mdchaney/CarrierWave-ImageSize

It does what you need pretty easily. Just stick it in your lib directory and then use it from your uploader by first loading the file:

require 'carrierwave/image_size'

and then including it in the class:

include CarrierWave::ImageSize

You need to add another field to your table to keep the extra info. If your picture is "avatar", you add "avatar_information" as a wide varchar field. It will then store size information for your image and various versions, as well as a content type. You then use "@user.avatar.image_width", "@user.avatar.thumb.image_height", etc. to get the size. It adds "image_width", "image_height", and "content_type" methods to all versions. It also works with nested versions.

It does require ImageMagick, specifically the "identify" command.

It would be a good upgrade to use MiniMagick or RMagick to get the size. It would also be nice for this to be turned into a gem. I just don't have time, but I am using this code on multiple web sites.

Hope that helps.

Avatar

Hi,

I'd like to inform you that this cast (as well as some others)
seems to stop working around the minute 5.31 (just after introducing "Tagging Features And Scenarios" paragraph).

I don't think it's me, infact the effect is reproducible, even breaking at the same time and the newer casts are working fine ...

Keep on the good job
Cheers Luca

Avatar

Forgot to do the follow up. It was a problem with a gem modifying routes which deleted the subdomain constraints.

Avatar

Can you post the full code for everything? I'm also wanting to save the step to the db. Thanks!

Avatar

Is there any reason to not use the fat arrow (=>) for every method definition in your classes?

Avatar

Ryan,

I had (and others on Overflow) an issue with stale or actually regenerated cookies. For instance. One login and the cookie is set with the :auth_code. If that cookie ever get out of sync with the db via regenerate or db reset the

User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]

code will fail. You can simulate this by changing one letter in the :auth_code either in the cookie or db. I agree this should never happen, but when it does it is ugly. This will fix it but I think there is a better solution:

def current_user
begin
@current_user ||= User.find_by_auth_token (cookies[:auth_token]) if cookies[:auth_token]
rescue ActiveRecord::RecordNotFound
@current_user = nil
cookies.delete(:auth_token)
end
@current_user
end

Avatar

I know that sending the actual emails/newsletters is not the focus of this episode, but I would like to see how Ryan would setup sending newsletters like this. I haven't been able to find a good example of sending group emails in Rails.

Avatar

I didn't know but you can manage more the flash hash...with a flash method and an after_filter I solved it...here are the flash methods if someone has a similar problem some day http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html

Avatar

ryan I was trying to do the same thing with my current proyect, and I have working the dynamic content, but I have problems with the flash messages, I have the same escenario as you, I send a submit action to a users#edit with a :notice => "hello" that redirects to deals#index (which have the notice message).... but when the callback is called the flash message is gone, it's a separate request to deals#current_user (I had trouble with using my users_controller given of decent_exposure gem)...anyway, I can do dynamic content, but the flash messages are lost and I don't know how to fix that. Please help

Avatar

Because of seamless integration with Warden, testing, and a really well-thought out system for managing multiple role contexts.

Avatar

Now you should update the CanCan episode as a part 2 to this revised episode. Thanks for putting the previous episodes together into a single lesson.

Avatar

For anyone still supporting a rails 2.3x app, the syntax that works for your migration is

def self.up
add_column :users, :tasks_count, :integer, :default => 0

User.reset_column_information
User.find(:all).each do |u|
 User.update_counters u.id, :tasks_count => u.tasks.count
end

end

def self.down
remove_column :users, :tasks_count
end

note the handling of tasks_count in the do loop...

Avatar

The default is to run all tasks in "production' mode. How would you make it run in the default environment?

Avatar

I found a workaround, but still curious if anyone who is also using ActiveModel was having issues with as_json/to_json methods. Maybe this is the wrong forum, if so, please feel free to delete!

Avatar

Thank you very much Ryan ! As usual a fantastic tutorial

Avatar

Very nice episode !
I can't seem to get Simplecov working with Minitest.
The output is of 0% file coverage when i write on top of the minitest_helper.rb file :

ruby
require 'simplecov'
SimpleCov.start 'rails'

Has anyone got this to work ?
Thanks a lot for your help.

Avatar

Thanks for that information regarding devise. I was also wondering why would I want to use it. Though, I'm sure that password resets and account verification wouldn't be that hard to accomplish with this episode as a starting point.

Avatar

I was actually wondering the same. I found something here that says it should show the time:

%p The `precise' time of day in 12-hour AM/PM format, with seconds.

But it doesn't work for me either, so I simply removed it (not that I would want the time shown on each and every command line).

Avatar

I'm anxious to see your capistrano chapter to this series. Any ideas when you're going to do it? Would be a great final installment.

Avatar

Thanks for the tip, Daniel. I'm re-writing from scratch (rather than trying to update) an app I did in Rails 2.3.8. Back then, I used the easy_roles gem based on one of Ryan's screencasts from that period. Since so much is new in 3.2.1 (including this excellent built-in authentication functionality) I was reluctant to risk blending old with new. I'll investigate cancan, and I appreciate your suggestion.

Avatar

Great cast. It's just what I needed.

However, I've had a surprise issue. I followed the video closely. My development environment functioned flawlessly (MacBook Pro, ruby 1.9.2-p290, rails 3.1.3). When loaded into my production server (Intel motherboard, Ubuntu 11.10, ruby 1.9.2-p290, rails 3.1.3) the call to the pdf class from my controller fails with an "uninitialized constant PatientsController::PatientsPdf" It's as though the internal rails "path" fails to find the file in the /app/pdfs directory. I could load the pdf class definition into my controller, but that's going to be a little messy. Any suggestions?

Avatar

yes, but they don't even find my house ! GoogleMap does !

Avatar

Generally you use Capistrano to copy it over. For Heroku you would use their config variables: http://devcenter.heroku.com/articles/config-vars

heroku config:add STRIPE_TOKEN=123

if Rails.env.to_s == "production"
  Stripe.api_key = ENV['STRIPE_TOKEN']
else
  Stripe.api_key = "public test key"
end

@tybro0103 mentioned you only need secure it when you're doing open source code. However I personally don't want my fellow developers to be able to refund payments, cancel my customers, or charge my customers copious amounts. Keep it secret, keep it safe.

Avatar

What do you not like about the solutions in the previous episodes?

Avatar

why don't you make the session a singleton resource? it would make sense since i can only have exactly one at a time. this would also fix the session_path("current") problem to be just session_path

Avatar

I'm not sure you'd really need to do anything different... Just follow the cancan episode

Avatar

Can Jbuilder templates be used inside of layouts? I tried creating a layout:

ruby
json.results do |json|
  yield
end

But unfortunately I just get {"results":{}}.

Avatar

Any thoughts on revising the episode(s) on Roles? Logging in is important, but I'm about to need to figure out how to allow an administrator to do some destructive actions that a less qualified User would not be permitted to perform. Thanks!

Avatar

for a quick&dirty support on jsonp with this, you can go with an after_filter:

ruby
after_filter do |controller| 
    if controller.params[:callback] && controller.params[:format].to_s == 'json'
      controller.response['Content-Type'] = 'application/javascript'
      controller.response.body = "%s(%s)" % [controller.params[:callback], controller.response.body]
    end
  end
Avatar

an issue i noticed with this was that when typing in a name that was in the database the autocomplete field would not highlight the name. if you did not physically click on the name that popped up and you simply added a comma or tabbed over it was treated as a new entry (the id wasn't added to to the token field, just the name). i solved this by going to line 1012 in the JS file and changing:

javascript
if(settings.allowCustomEntry == true) {
                    if(index === 0) {
                        select_dropdown_item(this_li);
                    }
                }

to just simply

javascript
   if(index === 0) {
                        select_dropdown_item(this_li);
                    }

When using Custom Data Entry you aren't getting that statement and that seemed to stop it from auto selecting the best match. Not exactly sure I did that this the best way but it appears to be working properly now.

Avatar

from the last time i've seen it, RABL is good with objects that are ActiveModel compliant. doesn't provide a lot of support if for example you have an Array/Hash object that you got from redis that needs to be represented as json.

Avatar

I get the following error when trying to implement this tutorial. I wanted to get this work and then alter to my needs so I have not made any modifications to the original code. Any one have any suggestions? I would really appreciate the help. Thanks!

undefined method `crop_x' for #User:0x007ff7594cb2f8

Rails.root: /Users/thomasbush/Rails/college
Application Trace | Framework Trace | Full Trace

app/uploaders/avatar_uploader.rb:47:in crop'
app/controllers/users_controller.rb:43:in
update'

Also not sure if this matters but my users system is set up with Devise, I handle roles and permissions with CanCan and I followed the #253 tutorial to get the basic carrierwave uploading working. All of course thanks to Ryan - railscasts is too good! Thanks.

Avatar

Devise has quite a few options like being able to verify accounts via email, recovery of lost passwords, temporarily blocking accounts with x number of failed log-ins etc.

Avatar

Hello Ryan,
If this is so simple now, is there a need to use gems like Devise and Sorcery anymore? What is it that you are doing in your consulting work? Please advise.
Thanks.
Bharat

Avatar

great episode as always. Thank you!

I need some advice from you. Your example works great if all versions of the uploaded image have equal widths and heights (i.e. width == height). In many cases, photos have different width and height, e.g. 640x480. And sometimes it needs to be rotated, so that width is 480px and height is 640px. If I want to have a "normal" version with dimensions 640x480 if picture is landscape and 480x640 if it is a portrait; with another "thumb" version 180x135 landscape and 135x180 portrait. Could you give some advice on how to achieve that?