RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

I figured the problem (or at least the issue that I was experiencing). It had to do with CSRF and how Ruby on Rails handle HTTP Post. I initially followed a tutorial on Braintree where it used regular html form. . This caused Rails to loose the session because of security associated with CSRF. To pass Rails's security check, I had to use <%= form_for @myobject, ... } do |f| %>. Lesson learned.

Avatar

so I have that working for individual records and thanks for that. What if I want to delete all entries? Thoughts?

I tried this which seems straightforward but no joy:

$scope.clearEntries = ->
    angular.forEach $scope.entries, (entry) ->
      entry.$remove()  
Avatar

Sweet. will take a look. thanks man!

Avatar

Hi, I am trying to use this solution in my application but it's not working for me. I am using Mongoid so that is only difference from this example. Here is my code:

class Country
include Mongoid::Document
field :name, type: String
field :abbreviation, type: String

has_many :states
has_many :equipment

end

class State
include Mongoid::Document
field :name, type: String
field :abbreviation, type: String

belongs_to :country
has_many :equipment

end

class Equipment
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Paperclip

field :description
field :modelNumber
field :title
field :categoryId
field :subCategoryId
field :city
field :askingPrice

belongs_to :country
belongs_to :state

has_mongoid_attached_file :photo

embeds_many :questions do
def find_by_id(question_id)
where(question_id: question_id).first
end
end

end

<%= form_for(@equipment) do |f| %>

<%= f.label :country_id, "Country" %>
<%= f.collection_select :country_id, Country.order_by([:name, :asc]), :id, :name, include_blank: true %>

<%= f.label :state_id, "State or Province" %>
<%= f.grouped_collection_select :state_id, Country.order_by([:name, :asc]), :states, :name, :id, :name, include_blank: true %>

<% end %>

My issue is the :states appears to be empty. I know this because the html output is:

All the option values that should be within the option groups are not there.

I would appreciate any assistance anyone can give. Sorry for the lengthiness but i wanted to give all the details.

Cheers,

Rich

Avatar

I know this is old but since I've lost 12 hours, leaving it for future reference...

My restart went fine and new PIDS for unicorn where given... but if I deleted "old" release folder it would break (unicorn was still pointing there). I thought it has to do with symlinking the in the wrong moment, but it was more sinister...

The unicorne process points to the wrong Gemfile, it fails or something and dies silently. (Ok not silently, but I overlooked).

GemFile not found

Unicorn restart/upgrade doesn't work

Adding this to my unicorn.rb solved the issue

ruby
before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "/rails_app/current/Gemfile"
end

You can also set ENV variable when invoking form capistrano like this, or probably just using capistrano-unicorn gem would be enough!

*It's really important that after change you stop/start unicorn after first redeploy. After that the "before_exec" block will go in memory and wait for the next deploy!

Avatar

Hey Everyone!
I have a few very basic questions about cache digests in rails 4.0

  • Do I need to include gem 'cache_digests" in Gemfile for rails 4.0 project?
    I didn't find a cache_digests gem in my project's rvm gemset neither did I put gem 'cache_digests" in my Gemfile. However <% cache xxx do %> actually worked. It wrote to cache and read from it like
    Read fragment views/pets/67-20130627183100171326000/1e699c80fb4b885994ecf5d1b8e61933 (0.1ms)

  • There is no cache_digests:nested_dependencies and cache_digests:dependencies tasks if I didn't include gem 'cache_digests" in Gemfile? Is that right?

Any helper's appreciated!

Avatar

Great lesson, Ryan. I share this because it slipped by me and it took a lot of troubleshooting to catch it. Hope it helps someone else. When you coded setupForm with $('#new_subscription').submit -> you said, "(#new_subscription), that is the default name that Rails will give it...". The Rails default name for my form wasn't working and I actually had to ID tag the whole form.

Avatar

When I substitute has_secure_password for

require 'bcrypt'
attr_reader :password
include ActiveModel::SecurePassword::InstanceMethodsOnActivation

when I do a signup he says unknown attribute: password_confirmation

Avatar

With Rails 4 and strong parameters, if we want this to work, we have to add resource_ids: [] in the permit call. For example :

ruby
params[:user].permit(..., role_ids: [])

Am I right? It doesn't work if we just add :role_ids in the permit call, because it's an array and not a scalar.

Avatar

Using capybara for web scraping

Gemfile
gem 'capybara', '~> 2.1'
gem 'capybara-mechanize', '~> 1.1'
ruby
require 'capybara'
require 'capybara/mechanize'

Capybara.configure do |config|
  config.run_server = false
  config.default_driver = :mechanize
  config.app = "" # to avoid this error: ArgumentError: mechanize requires a rack application, but none was given
  config.app_host = "http://railscasts.tadalist.com"
end

# Including Capybara::DSL in the global scope is not recommended but for the sake of this example:
include Capybara::DSL

visit "/session/new"
fill_in "password", :with => "secret"
click_button("Sign in")
# etc.. capybara cheat sheet: https://gist.github.com/zhengjia/428105

You can replace capybara-mechanize with any other headless capybara driver, e.g. poltergeist or capybara-webkit

Avatar

thanks a lot, this saved my life today

Avatar

Thank Ryan for this course.
Does any one can tell me how can i add UserMailer to js.erb file? or where i need to add UserMailer in controllers?(With this tutorial code)

Thanks everyone

Avatar

Hi Ryan,

Great episode once again. I have been using this a bit, but haven't been able to sort my associated objects directly from the Serializer. Does anyone know if this option is available? Or should I add the default sorting to the association (in the model file)?

Thank you!

Avatar

Scratch that, working again now, must have been a temporary hiccup

Avatar

Foreman + dotenv + dotenv-rails + heroku-config

My preferred configuration management tools.
Using them always with your .env file either on development or production, in heorku or VPS, with rake or capistrano, on Rails or any app.

Rails 3 / 4 with dotenv-rails

ruby
gem 'dotenv-rails', :groups => [:development, :test]

Rails + Heroku with heroku-config

shell
heroku config:push

Rails + Capistrano with dotenv-capistrano

ruby
require "dotenv/capistrano"

Plain old Ruby apps with dotenv

ruby
require 'dotenv'
Dotenv.load

Rake tasks

ruby
require 'dotenv/tasks'
task :mytask => :dotenv do ... end

Note: do not commit your .env file but commit the example

shell
cp .env.example .env
Avatar

+1 as well. I don't see why the pattern requires validations to be moved out of the model. If the validation keeps the persisted form of the data consistent, it should be part of any interaction with the model. If it is a validation that acts only on the form data, then I can see moving it into the form object. The password form object was a good example of that.

There's a really excellent pattern here, specifically I am thinking of a complicated sign-up process that is part of a single-page app. If you want to have a user fill in form data that goes to several models, the form model abstraction is perfect. Just make sure that it operates at the proper level of abstraction.

Avatar

Does anyone know if there is an issue with the video in this episode at the moment? Just subscribed and I seem to be able to play some of the newer episodes but not this one and some others (error is "Can't play video - Media Source has failed loading")

Avatar

Figured it out. The most recent version (2.2) has the evaluators_for method which reports users which have votes on a resource with the "metric".

This is my vote method which now includes "un-voting":

def vote
  value = params[:type] == "up" ? 1 : -1
  @public_comment = PublicComment.find(params[:id])

  have_voted = @public_comment.evaluators_for(:pubcom_votes_up) << @public_comment.evaluators_for(:pubcom_votes_down)

  unless have_voted.include?(@current_user) # vote
    @public_comment.add_or_update_evaluation(:"pubcom_votes_#{params[:type]}", value, @current_user)
  else                                      # unvote
    @public_comment.delete_evaluation(:"pubcom_votes_#{params[:type]}", @current_user)
  end

  respond_to do |format|
    format.js # vote.js.erb
  end
end
Avatar

I've implemented "un-voting". This railscast is dated if you're using the latest version of activerecord-reputation-system. Forget the voted_for? method on the user model and use evaluators_for.

Here's my vote method:

def vote
  value = params[:type] == "up" ? 1 : -1
  @public_comment = PublicComment.find(params[:id])

  have_voted = @public_comment.evaluators_for(:pubcom_votes_up) << @public_comment.evaluators_for(:pubcom_votes_down)

  unless have_voted.include?(@current_user) # vote
    @public_comment.add_or_update_evaluation(:"pubcom_votes_#{params[:type]}", value, @current_user)
  else                                      # unvote
    @public_comment.delete_evaluation(:"pubcom_votes_#{params[:type]}", @current_user)
  end

  respond_to do |format|
    format.js # vote.js.erb
  end
end

I'm tracking up votes and downvotes with 2 parameters. If anyone knows a way to keep it to 1 parameter but show # of upvotes and # of downvotes, let me know!

Avatar

I tried making it an array. It works. But It seems to be hacky. What exactly are we fixing?

Avatar

Oh, crap - I just realized that the default callback URL parameter is in fact redirect_uri - I made the mistake of specifying it as callback when I was playing around. My bad.

Avatar

I thought I'd add these notes for future n00bs to consider

  • You're most probably going to use Devise as your authentication solution - in that case, you want to change the method for finding the current user to be current user rather than the User.find_by_ code that's in the Doorkeeper initializer by default.
  • The OAuth2 gem uses certain defaults to generate the authorization URI - one of them is to assume that your OAuth provide route is /oauth/authorize which it will be if you use the Doorkeeper defaults, and the other is to use the parameter callback for the callback URI. The latter won't work though because the Doorkeeper gem default is to expect the callback URI to be specified with the redirect_uri parameter instead. So change callback= to redirect_uri=
Avatar

This is using symbol to proc. &:save is converted to {|obj| obj.save}. That means that any message you can send to an object is sendable. Really cool stuff! Use it in things like

ruby
class User
  attr_accessor :name, :email
  def initialize(name, email)
    @name, @email = name, email
  end
end

bobby = User.new("bobby", 'bboy@example.com')
annie = User.new("annie", 'aack@example.com')
[bobby, annie].map(&:email) #=> ['bboy@example.com', 'aack@example.com']
Avatar

How would you type cast as a float rather than an integer?

Avatar

failed: "sh -c '/etc/init.d/unicorn_Blog_new start'" whats the work around I have tried to fix the symlink , replaced it but .. its broken everytime .. need help...

Avatar

Ryan, pretty nice screencast as always. However, the migration is incorrect. It is irreversible due to the execute statement present. So, it can not be 'rake db:rollback'ed !! Specific up / down methods could be used here instead.

Avatar

I would like to download this source code and from my local machine come up with the same app. How do succeed. Please help

Avatar

Just wanted to say, thanks for this. Been able to change the html saved my A$$. I wrote this cute pagination style and regular markup(alas will_p) wasn't gonna cut it.

Avatar

Old thread as well, but perhaps this:
https://groups.google.com/forum/#!msg/plataformatec-devise/XFFrt4Gm-J4/NmEbV1rr8WcJ

could help you...

Short:
If you call your devise model differently (not "User" but "MyUser" for example) you have to make use of
my_user_signed_in?
resp.
current_my_user_registration_path etc. as in

html
    <div id="user_nav">
        <% if my_user_signed_in? %>
          Logged in as <strong><%= current_my_user.email %></strong>
        <%= link_to 'Edit profile', edit_my_user_registration_path %>
        <%= link_to "Logout", destroy_my_user_session_path, :method => :delete %>
      <% else %>
          <%= link_to "Sign up", new_my_user_registration_path %>
          <%= link_to "Login", new_my_user_session_path %>
      <% end %>
      </div>
Avatar

OK, kind of old thread, but I just have run into this as well.
It seems to be the 1.9 ruby syntax for Hashes.

Use
:method => :delete

instead of
method: :delete

if you are still on ruby 1.8.x

Avatar

I added the callback AND removed ENV[] but I am still getting the same error...

Avatar

I tried to add more entities. After I add more entities, I tries to add data and I got 422 status. And this is my code:

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  respond_to :json

  def index
    respond_with Post.all
  end

  def show
    respond_with Post.find(params[:id])
  end

  def create
    respond_with Post.create(params[:post])
  end

  def update
    respond_with Post.update(params[:id], params[:post])
  end

  def destroy
    respond_with Post.destroy(params[:id])
  end
end
app/assets/javascripts/news.js.coffee
app = angular.module("newsApp", ["ngResource"])

app.factory "Post", ["$resource", ($resource) ->
  $resource("/posts/:id", {id: "@id"}, {update: {method: "PUT"}})
]

@NewsCtrl = ["$scope", "Post", ($scope, Post) ->
  $scope.posts = Post.query()

  $scope.addPosts = ->
    post = Post.save($scope.newPost)
    console.log(post)
    $scope.posts.push(post)
    $scope.newPost = {}
]
app/views/news/index.html.erb
<div ng-controller="NewsCtrl">
  <form ng-submit="addPosts()">
    <input type="text" ng-model="newPost.title">
    <input type="text" ng-model="newPost.content">
    <input type="text" ng-model="newPost.source">
    <input type="submit" value="Add">
  </form>
  <ul>
    <li ng-repeat="post in posts">
      {{post.title}}
      {{post.content}}
      {{post.source}}
    </li>
  </ul>
</div>

Can I use this way?

Avatar

I have the same question. i think its a widget for mac editor.

Avatar

Hi Ryan,
Any plan on updating the video on how to use devise with Rails 4? Or a small addition of code snippets to this episode?
Thank You.

Avatar

Hi all,

my jquery datepicker didn't show without page refresh. I followed the exact step and I don't understand why. Any Idea please.

Avatar

Looks like the section element is being closed with a div instead of section.

Avatar

Any idea for how to adapt user.voted_for? for a specific metric? I'm tracking up votes and down votes separately for comments in my app and would like to display a "toggled" look if a user has already voted.

This is my vote method on my comments controller:

def vote
  value = params[:type] == "up" ? 1 : -1
  @public_comment = PublicComment.find(params[:id])
  if value > 0
    @public_comment.add_or_update_evaluation(:pubcom_votes_up, value, @current_user)
  else
    @public_comment.add_or_update_evaluation(:pubcom_votes_down, value, @current_user)
  end

  respond_to do |format|
    format.js # vote.js.erb
  end
end