The slides from last nights ‘Ruby User Group Berlin’ meeting.
It is practically a summary of the most recent post here plus examples.
Why your pretty, tested, Observer might not work
I normally have my observers tested, so the announcement “there is no mail comming” was pretty irritating at first, until i noticed that it was true. So i began my search … and after quiet some time digging and trying i found that i forgot to add the new observer to the config….
Normal Observer Setup
#environment.rb config.active_record.observers = :user_observer, ....
Automatic Observer Setup
And since i am forgetful, how about auto-loading all observers:
#environment.rb
observers = Dir.glob("#{RAILS_ROOT}/app/models/*_observer.rb").map do |file|
File.basename(file).sub('.rb','')
end
config.active_record.observers = observers
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
Automatically reduce image sizes with smushit
UPDATE: lossless image size reduction of whole folders
smushit.com reduces image sizes dramatically, lossless!
Great for logos/icons…, but does not work for gifs!
I put together a small script to automate smushing (as long as i cannot find a popper API).
Usage
ruby smush.rb http://my.file.com/123.png where/to/save.png
Install
requires ruby and rubygems
sudo gem install json
Store this into smush.rb
optional(if this task is to full/gets blocked):
cange the &task=89266837334214400 to something else or use random
#smush.rb
def store_smushed_image(url,file)
File.open(file,'w') do |f|
f.puts smushed_image_data_for(url)
end
end
def smushed_image_data_for(url)
require 'cgi'
url = CGI.escape url
require 'net/http'
require 'rubygems'
require 'json'
http = Net::HTTP.new('smushit.com')
path = "/ws.php?img=#{url}&task=89266837334214400&id=paste2"
resp, data = http.get(path, nil)
raise "oops #{resp}" unless resp.is_a? Net::HTTPOK
path = "/#{JSON.parse(data)['dest']}"
resp, data = http.get(path, nil)
data
end
#http://smushit.com/ws.php?img=http%3A%2F%2Fwww.famfamfam.com%2Flab%2Ficons%2Fsilk%2Ficons%2Fdrink_empty.png&task=89266837334214400&id=paste2
url = ARGV[0] || "http://www.famfamfam.com/lab/icons/silk/icons/drink_empty.png"
file = ARGV[1] || 'out.png'
store_smushed_image(url,file)
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