RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

excellent revised episode!

Using the t() method, it can sometimes be confusing which key in the i18n file Rails is trying to look up.. there doesn't seem to be a consistent naming convention in Rails.

e.g it uses different locations for form labels, buttons, helpers, titles, strings in controllers or models, etc..

The following page provides a table with examples, as well as a tip on how to monkey-patch the i18n Gem in development mode, so Rails will tell you the i18n-keys it tries to look up.

http://www.unixgods.org/~tilo/Rails/where_is_Rails_trying_to_lookup_L10N_strings.html

I hope you'll find it useful.

Avatar

Thank you so much for this. I did not know we can use Model attributes in a more simpler than i used to do it all the time.

Avatar

Have you tried to install rbenv for the root user too?

Avatar

Ryan,

I wrote a very simple provisioning tool to help people setup a new instance on VPS. It has a bonus feature to setup / teardown Linode instances interactively, by choosing plans and datacenters, etc.

https://github.com/kenn/sunzi

I hope this helps to anyone who scratched their head dealing with chef / chef-solo!

Avatar

Made a mistake with the preseed file. Should read

mysql-server-5.1 mysql-server/root_password_again password <%= lv_password %>
mysql-server-5.1 mysql-server/root_password password <%= lv_password %>
mysql-server-5.1 mysql-server/start_on_boot boolean true

Avatar

I'm trying to use Passenger and have now twice hosed my install.

I can successfully complete this line of the script in the show notes

ruby
# rbenv
curl -L https://raw.github.com/fesplugas/rbenv-installer/master/bin/rbenv-installer | bash
vim .bashrc # add rbenv to the top
. .bashrc
rbenv bootstrap-ubuntu-10-04
rbenv install 1.9.3-p125
rbenv global 1.9.3-p125
gem install bundler --no-ri --no-rdoc
rbenv rehash

But when I go to run

passenger
# Phusion Passenger (instead of Unicorn)
sudo apt-get -y install libcurl4-openssl-dev apache2-prefork-dev libapr1-dev libaprutil1-dev
sudo gem install passenger --no-ri --no-rdoc
sudo passenger-install-apache2-module
sudo vim /etc/apache2/apache2.conf # modify as instructed by installer

I get a sudo: gem: command not found error.

If I exit the deployer session and su deployer from root, I get this error: /home/deployer/.rbenv/bin/rbenv: line 20: cd: /root: Permission denied

Then running ruby -v gives me this error bash: ruby: command not found when previously that worked for deployer.

Any ideas what I'm doing wrong?

Avatar

On the other hand there is an argument for putting the protection into the model rather than controller:

Protecting attributes from within controllers sounds like a setup to have multiple points of fault. If I have more than one controller making saves/updates on the same model (ignoring a debate over if that is good design), then I have to remember to protect attributes in multiple controllers. If I handle mass assignment from the model, there's a single, definitive barrier between submitted params and persistence, irrespective of where that data originated. -- @Eleo

@Eleo exactly. That's what I tried to say [to] dhh in my gist. Controller has nothing to do with unintended params. It doesnt filter. It handles, manages, controls business logic.
IMO You should write your controllers way described below:
1) have all critical fields protected/updateable - accessible
2) control saving new record in controller using role checks, dependencies and abilities. Not just by filtering :user_id
3) Never simplify business logic for "update". People got role checks in "create" but trying to manage just "update_attributes" in edit and that's why this has happened. If you check role - check it on create and on update.

Don't be lazy. sic! -- @homakov

See: Mass assignment vulnerability - how to force dev. define attr_accesible?

Avatar

Maybe we can have an episode about globalize3 next?

Avatar

Yes but I don't want to do it manually each time I deploy an update...

Avatar

We are using tolk, simple plugin, works well after tweaking: https://github.com/dhh/tolk

Avatar

From what I can tell, you would need to change it to include the application name.

Avatar

Delete the .pid et sock files before trying to start Unicorn again.

Avatar

Any idea, why localizing nested attributes is unbelievable painful? Consider this setup, where you need a lot of repetition to create correctly localized error messages.

Am I doing it wrong?

Avatar

Great screencast on basic I18n use in ruby!

Another unmentioned tool for managing your YAML files is Locale, check it out.

(Disclaimer : I'm a Locale developer)

Avatar

Ryan,

Awesome episode, would you suggest using this approach to setup vagrant for development?

Avatar

I was unable to get the crop working using RMagick, so I investigated what would be the equivalent using MiniMagick.

Based on this discussion on stackoverflow, I was able to come up with this working solution. This method would be saved in the User model and there is no longer a crop method within the AvatarUploader CarrierWave object.

There is one minor issue with this code, which is that the large version of the image becomes the master copy of that image. If you do not care about keeping the high resolution version of an uploaded image, this issue will not matter to you.

ruby
class User < ActiveRecord::Base
  mount_uploader :image, ImageUploader
  
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
  after_update :crop_image

  def crop_image
    if crop_x.present?
      mini_magick = MiniMagick::Image.open(self.image.large.path)
      crop_params = "#{crop_w}x#{crop_h}+#{crop_x}+#{crop_y}"
      mini_magick.crop(crop_params)
      mini_magick.write(self.image.path)
      image.recreate_versions!
    end
  end
end
Avatar

You can use a preseed file to automate the mysql installation, Ubuntu (10.10)

you can use something like (not tested)

run "#{sudo} debconf-set-selections /tmp/mysql_preseed"
run "#{sudo} apt-get -y install mysql-server"

The preseed file itself (you can run this through erb) or replace
the erb code with your mysql password:
mysql-server-5.1 mysql-server/<%= lv_password %> <%= lv_password %>
mysql-server-5.1 mysql-server/<%= lv_password %> <%= lv_password %>
mysql-server-5.1 mysql-server/start_on_boot boolean true

I switched from capistrano to sprinkle, because sprinkle can be programmed to verify the deployment and I don't have to duplicate
capistrano recipes for each Rails project.

Avatar

I recently released a very simple alternative to Chef if anyone's interested: https://github.com/cmer/shoestrap

Avatar

Unicorn is significantly faster than Passenger. A well-tuned MySQL install performs similarly to a well-tuned Postgres install.

Nginx is generally much simpler to setup than Apache. It's also faster and less resource hungry.

Avatar

Heads-up! New approach!

DHH advises against putting mass-assignment protection into the model:

The basic idea is to move mass-assignment protection out of the model and into the controller where it belongs.

The whole point of the controller is to control the flow between user and application, including authentication, authorization, and as part of that access control.

This new approach is an extraction of the slice pattern and we're calling the plugin for it strong_parameters (already available as a gem as well).

See: http://weblog.rubyonrails.org/2012/3/21/strong-parameters/

p.s. Here's the blog of the Russian programmer, Egor Homakov, who cleverly brought this vulnerability to everyone's attention. BTW, the rails team supposedly ignored him ("guys in rails issues ingored me and my issue"). So, kudos to Egor!

Avatar

Hi guys,
does anyone know how to automate mysql installation?
I'm stuck when that blue screen pops up and asks for mysql password!

I found great resource here about streaming data from a capistrano run helper: http://errtheblog.com/posts/19-streaming-capistrano

Avatar

And all unobtrusive javascript things doesn't work anymore in the partial (jquery-ui autocomplete, $(".dynamic_header a").click(function()...)

I have no heavy traffic so I'm back to fragments caching instead of full page

Avatar

That's the why Ryan suggests the "h" method. It's an easier way to access the @template attribute.

That way you could do something as:

ruby
  def name
    handle_none user.name do
      h.link_to(user.name, h.user_path(user))
    end
  end
Avatar

I have an issue when I want to restart Unicorn, the pid and sock files aren't deleted when it is stopped so when Capistrano want to start Unicorn, it fails due to the files already present.

Anyone have an idea to fix this?

Avatar

Made our heads hurt the first time but made a lot more sense after watching it again! Great work.

We found that it pairs up nicely with the Backbone Codeschool course, which let you play with the individual MVC components one by one, and then your Railscasts show the overall architecture of a Backbone app and how the individual bits come together.

There seem to be a few interesting Backbone plugins springing up in the community - Marionette, LayoutManager, ModelBinding and Forms to name just a few we've come across - any chance of a screencast covering some of these?

Avatar

Switching branches often makes the rake completion somewhat less usable. So I changed it up a bit to use the md5 sums of all the rake files instead of looking at timestamps:

zsh
#compdef rake

if [[ -f Rakefile ]]; then
  sum=`md5 -q Rakefile **/*.rake | md5`
  if [[ ! -f .rake_tasks.$sum~ ]]; then
    rake -s --tasks | cut -d ' ' -f 2 > .rake_tasks.$sum~
  fi
  compadd $(cat .rake_tasks.$sum~)
fi

This will leave a bunch of .rake_tasks.[...]~ files around so the fast completion will continue to work even when switching between branches that have different rake files.

Avatar

Thanks for posting about this. Tried it out tonight - good stuff.

Avatar

Has anyone used Minitest to test associations in their models? I can't seem to find any examples of this kind of testing. I used to use rspec and shoulda and do something like this in my model test:

it { should have_many(:products).through(:buying_guides_products) }

how would I go about testing something like this with minitest (preferably mintiest::spec if you're using that) Thanks for any help!

Avatar

And another issue.

private_pub.ru should contain:

Faye::WebSocket.load_adapter('thin')

Taken from https://github.com/faye/faye/issues/128

Avatar

If your assets directory has a lot of compressible files, e.g. text, XML, JS, etc. rsync -z to compress can be worthwhile. Rather than -r which just recurses into the directory, consider -a (--archive) which preserves timestamps, ownership, symlinks, etc. Depending on circumstances this can be less surprising...

Avatar

Hi guys,

I'm a newbie so in my case my webpage is:

< label for="table_basket" >Basket</ label >
< select id="table_basket" name="table[basket]" >< option value="" >Please
select< /option >
< option value="1" >Awesome< /option >
< option value="2" >Normal< /option >< /select >

< label for="table_apple" >Apple< /label >
< select id="table_apple" name="table[apple]" >< option value="" >Please
select</ option >
< option value="1" >Green< /option >
< option value="1" >Red< /option >
< option value="2" >Yellow< /option >
< option value="2" >White< /option >< /select >

< input name="commit" type="submit" value="Create Table" />

in the app/views/apple/index.html.erb I have

<%= form_for @table do |f| %>

<%= f.label :basket %>
<%= f.collection_select :basket, @basket, :id, :name, {:prompt => true} %>

<%= f.label :comune %>
<%= f.collection_select :apple, @apple, :basket_id, :name, {:prompt => true} %>

<%= f.submit %>

<% end %>

And I change the apple.js.coffe file in this

jQuery ->
apple = $('#table_apple').html()
$('#table_basket').change ->
basket = $('#table_basket :selected').text()
options = $(apple).filter("[label=#{basket}]").html()
if options
$('#table_apple').html(options)
else
$('#table_apple').empty()

but it doesn't work I think the problem it's here in this line

options = $(apple).filter("[label=#{basket}]").html()

options doesn't get the 'value' of the option attribute in the select list menu

Is it a simple syntax error?

thank you in advance,

A

Avatar

I've used this tutorial before (2 weeks ago) and produced the same store application as Ryan. However, when I attempt to follow this tutorial again (on a new machine, running Ubuntu 11.10, same as before) I come up with this error http://pastie.org/3688534 after running the command $ rails g bootstrap:install and then refreshing the browser. Also note, the override.css file already contains the added padding to the top of the body - it's like it knew I was going to change it. If I comment out the @iconSpritePath and @iconWhiteSpritePath I can get localhost:3000/products to work but...

When I get to the point where I'm supposed to use the command $ rails g bootstrap:themed products -f it won't run correctly. I get this response on the command line http://pastie.org/3688555

I'm following the tutorial exactly. What could be causing this to happen?

Avatar

Whilst I appreciate Ryan has a bigger audience than thoughtbot (otherwise CopyCopter might not be shutting down as a paid service), this screencast is almost a word for word copy of the one Dan Croak did here a couple of days ago: http://robots.thoughtbot.com/post/19388751626/copycopter-is-now-open-source

Not saying that's good or bad, it just feels "off" somehow (not as off as Christopher Dell's ad for his competing product, but you know what I mean).

Avatar

For some reason when it runs the bootstrap it prompts for a sudo password since each command in the script is attempting to sudo, but does not accept my input when typing. (In fact, in my zsh term it displays the password as I type) Has anyone else had this issue? I enter it at the beginning as Ryan does when prompted; I would think it would be passed through. Ubuntu is the default server install in my case.

[xxx.xxx.xxx.xxx] sh -c 'rbenv bootstrap-ubuntu-11-10'
[out :: xxx.xxx.xxx.xxx] [sudo] password for deployer:

Avatar

Nice tutorial, thank you very much Ryan.
Can you explain more clearly about sorting with Ajax, please? When user click header column (e.g: description), the js code in application.js is called. Then params[:sort] and params[:direction] are sent to controller. After variable @products is set, the js code in index.js.erb is executed, then product table is rendered. Do I think right, or not? If right, I don't understand why: when js code in application.js is called, the js code in index.js.erb is not executed immediately.
If I'm wrong, please explain for me about process flow when user click header column.
And one thing, what different between using ajax getScript and using :remote => true? If I want to use :remote for sorting, what things I need to change?
Thank you very much

Avatar

I think he means the:

upstream unicorn {

to

upstream unicorn_<%= application %> {

Otherwise you'd have a lot of "upstream unicorns" loaded. I wondered this myself, and was going to test it. If no one else posts, I'll tell what I find out.

Avatar

A heads up that if you add '--yes' to the end of the add-apt-repository lines, it will not prompt you to add the repo in the default install on Ubuntu 11.10.

Avatar

I found this blog post on GitHub about their transition from nginx/haproxy/mongrel to nginx/unicorn. Sounds intriguing.

https://github.com/blog/517-unicorn

Avatar

Copycopter will be shutting down on April 15. It's a shame to see useful features die. I'm sure that they had good reasons, unlike they're like Google with Google Wave or Fox with any awesome show that died after 1/2 - 1 season.

Avatar

Hey, great video :)

Just a minor issue: I'm using branch other than master for deployment and in my opinion deploy.rb:44 should not include hard-coded branch.

Avatar

I doubt heroku doesn't know about this possibility... ;-)

Avatar

Hello

Is this still relevant these rails 3.X days?
Is it Gem-ified...?

TIA

Avatar

Looks like it is:

https://github.com/railscasts/episode-337/blob/master/blog-after/config/recipes/templates/nginx_unicorn.erb

erb
 upstream unicorn {
    server unix:/tmp/unicorn.<%= application %>.sock fail_timeout=0;
 }
Avatar

Copycopter allows clients to edit text on a site without a developer. Shutting down your copycopter server would be no different from just editing all the text yourself to begin with. In my case, I will probably be the only person who uses Copycopter, but even just playing with it has helped me finally get a better grip on locales and I18n in my Rails apps.

Avatar

@migane's solution actually worked in Rails 3.2 as well, thanks!

Avatar

Similar to @migane's post, how can we implement highcharts in Rails 3.2?

Avatar

It doesn't override the files themselves, but those will be used as defaults. All of your locale data will go into copycopter database. You can remove your original files then, and/or you even replace them with a version extracted from the current copycopter database. This means by time you can even shut down your copycopter server.

Avatar

I'm pretty curious myself. I'm getting ready to do some hard profiling on our multiple apps at work to try and find the best setup for performance.

Anyone have any benchmark information on using Unicorn/nginx over Passenger/Apache?

Avatar

Might want to take a look at Locale which provides a lot of Copycopter's functionality, but has a more I18n-oriented approach.

Being an external serivce, there is very little setup needed to get it in to production.