RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

This is probably a dumb question but, does using Globalize3 mean our original table (say Articles) now has empty columns for attributes that are translated and stored in the translation table?

Avatar

I've heard that claim before and it typically means your specs do a large amount of AR object creation on the fly via factories. For some use cases, MetaWhere used to actually increase benchmarked performance.

As for Squeel, I haven't done any such benchmarking, but I'd be interested to see the results.

Avatar

hello I am trying to save to the field society_id which takes the data from User table (current_user.society_id). I am using Devise.

def self.ids_from_tokens(tokens)
tokens.gsub!(/<<<(.+?)>>>/) { create!(name: $1, society_id: current_user.society_id).id}
tokens.split(',')
end

It gives an error undefined variable current_user.

Current_user is defined by Devise for controller and view but it doesn't work with model i guess.

can someone help me how to make it work

Avatar

Help!, I'm tring to create an omniauth-identity login following the screencast but I get the following error;

ActiveModel::MassAssignmentSecurity::Error

Can't mass-assign protected attributes: password, password_confirmation

Avatar

I don't really see the practical benefit of trying to replace SQL code with Ruby, if only for very basic queries.

What I'm really interested in is if SQL scripts can be called and returned to ActiveRecord from Ruby ... so that Ruby and SQL code are separated :-)

Avatar

This is awesome, works great on development but when I pushed to production I get this error in the log...

URI::InvalidComponentError (bad component(expected host component):

Thanks in advance for any help out there

Avatar

Thanks a lot for this :)

Ryan, do you by any chance have in mind doing an episode similar to this, but focusing also on polymorphic associations, or associations in general?

Maybe it's just me, but I find very difficult to work with Arel when in those situations. Specially polymorphic. The solution is always do SQL by hand.

Avatar

We ran into a lot of issues with Rails counter-caches in our app, so we made a gem to solve all of them. Maybe it'll help you as well? Would love feedback, too.
https://github.com/bestvendor/counter_culture/

Avatar

In my previous post, forget about Capibara.

I got a sample how you could test some controllers..
In my setup I use; factorygirl and RSpec.

Ruby
require 'spec_helper'
module Api
  module V1
    describe UserSessionsController do
      render_views
      describe "authenticate" do
        it "authenticates correctly" do         
          user = FactoryGirl.create(:user)          
          post :create, :email => user.email, :password => user.password, :format => "json"  
          user.reload
          response.cookies['user_token'].should eq(user.user_token)
          response.should be_success
          body = JSON.parse(response.body)
          body['id'].should eq(user.id)
          body['email'].should eq(user.email)
          body['user_token'].should eq(user.user_token)
          body['password'].should equal nil
          body['profile'].should_not be nil
          
        end
        it "should return a json user"
          user = FactoryGirl.create(:user) #this user
          @request.cookies['user_token'] = user.user_token #  if you need an auth cookie..
          get :show, :id => user.id, :format => "json"
          response.should be_success
          body = JSON.parse(response.body)
          body.should have(1).user #test if only one root object is returned (sometimes you dont want to have a json root..)
          body[0].should have_key("user") #test root key...
          body[0]['user'].should have_key("id")
          body[0]['user'].should have_key("email")
          body[0]['user'].should have_key("friends")
          body[0]['user'].should have_key("profile") #test if the user has an associated profile
          body[0]['user'].should have_key("updated_at")
          body[0]['user']['profile'].should have(1).profile # test that the user returns only 1 profile.
          body[0]['user']['friends'].should have(3).friends #test that the user has 3 friends
        end
      end
    end
  end
end

I hope this helps you..

Avatar

Hello everybody,

It is very nice tutorial,

But guys, i spend my 2-3 days to discover how we can render .liquid file on .liquid view. same as we can do in rails partials render method.

please help me.
Please..

Avatar

When I write "tagName: 'li'" im stuck with an error?

Error: Parse error on line 5: Unexpected '{'
(in /rails_projects/raffler/app/assets/javascripts/views/entries/entry.js.coffee)

Avatar

I'm sure you found you solution by now, but if anyone else is looking around for this:

article.rb
has_many :taggings, :as => :taggable, :dependent => :destroy
has_many :tags, :through => :taggings

And since this is polymorphic these two lines would go into whatever model you wanted to be taggable.

tag.rb
has_many :taggings, :dependent => :destroy
has_many :taggables, :through => :taggings
tagging.rb
belongs_to :taggable, polymorphic: true
belongs_to :tag
Avatar

I was having issues with upper/lower case searching with pg_search. I then went and changed my query to match something like to_tsvector('english', title) @@ to_tsquery('english', :q) and it worked. Do you have any ideas why this would be the case?

Avatar

Absolutely, you can do whatever you want in your steps views.

Avatar

What are the performance concerns with using Squeel?

We recently removed Metawhere from our Rails 3.0.x app and our specs complete around 5X faster.

Avatar

Running rails 3.1.3 with rack-offline 0.6.2 and i lose the stylesheet everytime on refresh. My stylesheet names are in tact as I'm able to disable the timestamp hash that gets appended in the video. i tried the arsduo rack-offline fork to no avail. I know this video is a little older, any updates to know about for newer versions of Rails?

Avatar

Have you tried running rbenv rehash again.
I had to re-run rbenv rehash after installing the passenger gem so that passenger-install-apache2-module would work.
Also, I didn't sudo the gem installation.

Avatar

I'd second this. I wouldn't have written Ransack if there weren't use cases for it, but I do feel some guilt, sometimes, over making it easy for people to do the wrong thing. I'd also note that it's important, for public-facing and high-traffic search forms, to consider an inverted index search of some kind.

Avatar

Ransack is great for simple cases, however imho on more complex scenarios I'd rather write search from scratch, otherwise one ends up with those long names like name_matches_or_translation_name_matches that are somewhat unintuitive, and some even more complex scenarios cannot be expressed at all. So when search requirements bypass a certain threshold one should replace Ransack with a solution from scratch rather than fight it's API.

Avatar

I'm also looking for a many-to-many solution that can handle more than one field. Has anyone managed this?

Avatar

You are right about your input/comment - One thing to watch out for when using QC (or any background job manager) with Rails is jobs enqueued from after_create / after_save callbacks that use the new record. We've found that you must use after_commit instead to ensure that the record has been committed to the DB before the worker tries to find it by ID.

I am interested to see Ryan Smiths response or comments on this too.

Avatar

I love Ernie Miller's two main projects (Squeel & Ransack / previously metawhere & metasearch).
As much as Squeel cleans up DB look ups, I find Ransack totally brilliant, it makes standard (and you can go quite sophisticated) searches in indexes so easy and flexible!

Avatar

I've used Squeel exclusively for developing my tagging library. Compared to acts as taggable on steriods the code is very readable.

https://github.com/bradphelan/rocket_tag

It makes writing composable SQL a breeze.

Avatar

Nice bit to know about calling "my" to get the original context.
I'd started creating variables before the where clause so I could call them, I think "my" is better.

Love Squeel. Love that I don't have to mess with ARel.

Avatar

We use Squeel on all of our projects and it totally rocks. It's a really pretty little DSL.

Avatar

I have a gist integrating Squeel with CanCan ( https://gist.github.com/1523940 ) that lets one do outer joins and less common operations:

ruby
# example domain names: domain.com, sub.domain.com

# in ability
can :manage, Domain, :permissions.outer => {:user_id => user.id}
can :manage, Domain, :name_reversed.matches => "#{domain.name_reversed}.%" # descendants

# in controller
@domains = Domain.accessible_by(current_ability) # or
authorize! :read, @domain

Hope Ryan will integrate it soon.

Avatar

You can also override from using Class.from('select * from blah') in case you need to do nested selects.

Avatar

I still dont agree with your pattern. What happen when you have a nested article - picture - comment?

Your technique will see the article_id and load it as the commentable while we are trying to comment on the picture.

That being said, I agree that being able to add scopes is a plus and I find that it is your biggest argument.

Avatar

Ok, it makes sense.

Thanks.

Avatar

Since Squeel converts down to ARel, which underpins pretty much all of ActiveRecord, you shouldn't have any problems related to DB drivers.

Avatar

Thanks Ryan.

This is good if all database drivers support it. Otherwise we'll have the same issue as using plain old SQL.

IMHO, unless something like this is adopted by Rails out of the box, the prons and cons of using a gem with another DSL almost even.

Avatar

How about a bit of DRY. I have this in lib/hstore_accessor.rb ( see https://gist.github.com/2834785 ):

ruby
module HstoreAccessor
  def self.included(base)
    base.extend(ClassMethods)
  end
  
  module ClassMethods
    def hstore_accessor(hstore_attribute, *keys)
      Array(keys).flatten.each do |key|
        define_method("#{key}=") do |value|
          send("#{hstore_attribute}=", (send(hstore_attribute) || {}).merge(key.to_s => value))
          send("#{hstore_attribute}_will_change!")
        end
        define_method(key) do
          send(hstore_attribute) && send(hstore_attribute)[key.to_s]
        end
      end
    end
  end
end

ActiveRecord::Base.send(:include, HstoreAccessor)

and in config/initializers/active_record_extensions.rb

ruby
require "hstore_accessor"

Then we can do

ruby
Class Widget < ActiveRecord::Base
  hstore_accessor :properties, :size, :shape, :smell
end
Avatar

Was having problems Updating the widgets when saving a lecture through update_attributes(...). It was a matter of accessibility of the attributtes of widget.

lecture.rb
class Lecture < ActiveRecord::Base
  attr_accessible :name , :order , :html, :widgets_attributes 
  has_many :widgets
  accepts_nested_attributes_for :widgets,  :allow_destroy => true
end
widget.rb
class Widget < ActiveRecord::Base
    belongs_to :lecture
    attr_accessible :width, :height, :xpos, :ypos, :source
end

The last line of the widget class made all the difference.

Avatar

As a follow up to my previous comment i used the following
in my routes and dropped the resource :sessions

ruby
  get 'signup', to: 'users#new', as: 'signup'
  post 'signup', to: 'users#create', as: 'signup'
  get 'login', to: 'sessions#new', as: 'login'
  post 'login', to: 'sessions#create', as: 'login'
  get 'logout', to: 'sessions#destroy', as: 'logout'

NB: i still have resource :users for the full rest interface there

also with this i had to change the login form to be form_tag login_path
and my signup form to be simple_form_for @user, url: signup_path

Avatar
ruby
Blog::Application.routes.draw do
  scope ':locale', locale: /#{I18n.available_locales.join("|")}/ do
    resources :articles
    root to: 'articles#index'
  end
  match '*path', to: redirect("/#{I18n.default_locale}/%{path}")
  match '', to: redirect("/#{I18n.default_locale}")
end

This routes config will have redirect loop error. When you go to http://localhost:3000/abc you will see it.

So i suggest config routes like this to avoid redirect loop error.

ruby
Blog::Application.routes.draw do
  scope ':locale', locale: /#{I18n.available_locales.join("|")}/ do
    resources :articles
    root to: 'articles#index'
    match '*path', to: redirect("/#{I18n.default_locale}")
  end
  match '*path', to: redirect("/#{I18n.default_locale}/%{path}")
  match '', to: redirect("/#{I18n.default_locale}")
end
Avatar

In case anyone is interested, I was able to achieve this behavior outside of the controller, by just "clicking" the add_field buttons with js

Avatar

Did you fix this issue? Could you share the solution? Thanks.

Avatar

Is it possible to do sorting on two columns like:

ascend_by_last_name.ascend_by_first_name?

Avatar

depending on your distro you might need to do some installation-fu

e.g. for an ubuntu install recently i had to do apt-get postgresql-contrib

Avatar

Hey Zolzaya,
I did some research myself. I think i will try to split my controller and response tests with Capibara gem. What I test in my controllers are the controller logic. I still need to get started with testing on my json responses. Ill give you a update...

Ruby
require 'spec_helper'
module Api
  module V1
    describe UserSessionsController do
      describe "authenticate" do
        it "authenticates correctly" do         
          user = FactoryGirl.create(:user)          
          post :create, :login => user.email, :password => user.password, :format => "json"    
          response.should be_success
        end
      
      describe "fail authentication" do 
      end
      
      describe "logout" do 
      end
      
      
    end
  end
end

One thing i have to use :format => "json" to get json responses, it would be great if it went automatically.

One more thing check RABL git how to test your RABL responses.

https://github.com/nesquena/rabl/wiki/Testing-with-rspec

Here you go mate ;)

Avatar

In sessions#create,

instead of render "new"

try redirect_to login_url

Someone in the original version of this episode also mentioned dropping the resources :sessions line from routes.rb

Avatar

Ok I figured it out after a weekend relaxing :p
You can put in your rspec:

ruby
module Api
  module V1
  end
end

This will perfectly work. In my other attempts before the weekend i placed do behind V1 and Api, that will just not work. :)

Avatar

I just notice something with this, when you pass a failed login or signup back you lose the /login(/signup) and get given /sessions(/users)
any ideas on how to fix this?