It should behave like resource

One pillar of my high code-coverage is this little plugin, which allows you to simply state that a controller or a action should behave RESTfully.

So far it is experimental, meaning it works on my machine 🙂
Any testers and contributes highly welcome.

Install instruction and usage.

Example

describe UsersController do
  before :each do
    login_as :quentin #if your controllers need login
    @item = @user = stub_model(User)#or anything else that has a to_param method
  end

  behave_like_resource
end

Happy hacking with Conditions, Count, Group, Joins, Random, Scope and Select

UPDATE: use http://github.com/grosser/random_records for random

This morning i wanted to:

  • Select records
  • Scoped
  • Random
  • Unique
  • Joined through 2 tables

The scope
Person.filmmakers

named_scope :filmmakers, :joins=>{:team_memberships=>:movie}, 
  :conditions=>{'movies.status'=>'online'}, 
  :group=>'people.id'

So we want people that participated in a movie, and add group so that there are no duplicates.

Counting
Person.filmmakers.count

Does not work! Count discards group, since cont(:group=>something) would result in [[a,number_of_records_with_a],…]
So lets add a counting that works as expected, by returning the sum of all count results(sum of the distinct values).

scope_from_above do
  def count
    super(:group=>'people.id').size
  end
end

Random
Person.filmakers.random(3)

Normally random looks like this.

#UPDATE: use http://github.com/grosser/random_records for random 
class ActiveRecord::Base
  def self.random(num=1,options={})
    return [] if num.zero?
    num_records = count
    find(:all, {:offset => [rand(num_records),num_records-num].min, 
      :limit=>num}.merge(options))
  end
end

It does not use the scope count that we defined, but the regular count, so we have to pass in count separately.
And it returns records where the id is set to Movie.count or the last movie id, very strange.

Final scope and random

named_scope :filmmakers, :joins=>{:team_memberships=>:movie}, 
  :conditions=>{'movies.status'=>'online'}, 
  :group=>'people.id' do
  def count
    super(:group=>'people.id').size
  end
    
  def random(num=1,options={})
    #select people.* or id will always be Movie.count WTF
    super(num,options.merge(:count=>count,:select=>'people.*'))
  end
end

#UPDATE: use http://github.com/grosser/random_records for random 
class ActiveRecord::Base
  def self.random(num=1,options={})
    return [] if num.zero?
    num_records = count
    find(:all, {:offset => [rand(num_records),num_records-num].min, 
      :limit=>num}.merge(options))
  end
end

Enhanced RSpec Profiling

If normal rspec profile output is not enought, try this enhanced rspec profile formatter!

Example

Groups:
5.1150300 Movie
4.9603220 Icon
1.7279670 User
1.4466160 Person
...

Single examples:
4.8707710 Icon refresh! resizes existing thumbs
0.9086340 Review releases the movie
0.5203390 Movie finds invalid
...

Install

script/plugin install script/plugin install git://github.com/grosser/rspec_enhanced_profile.git

#add to spec/spec.opts:
--format RspecEnhancedProfile:tmp/profile.txt

Profiling RSpec

Small option, but took me 2 hours to find :/
This will automatically generate reports for your test-runs.

It only shows single examples, which is sad since i would also want to know which controller_specs take the longest…

Output:

Top 10 slowest examples:
0.5215740 User downgrades to a person
0.4326950 User finds invalid
0.1914630 User remembering unsets remember token
0.1218360 User is valid
0.0903790 Festival is valid

Install:

#spec/spec.opts
--format profile:spec/profile.txt