Wednesday, 23 September 2009

Holy crap that was a mind-f**k

nested forms - you have to love 'em.
Nesting with has_many was not too much of a problem. Follow the railscast and it all seems to work just fine - yes it was fiddly, but in the end it comes good.
Nesting with has_one - a total mind fuck.
With has_many you can use association.build to build all the objects you want and then use yr bog-standard controller to handle it for you with the update.
But has_one has a real gotcha. If you try and create two objects - which you may have to to get round the nil problem when using the form_for thingy, then if you try and use association_build, it updates both of them - immediately orphaning one of them as you can only have one associated object. And then all manner of horribleness starts.
After a long, long, long time screwing around with this - came up with the following:
def client_attributes=(client_attributes)
#this little beaut Returns the associated object. nil is returned if none is found (ie on new).
cl = client(force_reload = false)
if cl == nil
build_client(client_attributes)
else
client_attributes.each do |key, value|
unless key == 'id'
cl["#{key}"] = client_attributes["#{key}"]
end
end
client=(cl)
end
end

It is the normal virtual attribute you use to pick it up from the form, and then whack a method in the model. But you have to handle two different situations - one when it is a new build, in which case you won't have an existing client object - so you can go ahead and build it, and the other time when you do.
Then I have manually gone through the new attributes - and leaving aside the id, taken the new values by hand into a temp object (cl), given it the new values from the hash you pass over, and then save it to the child object (client).
Then when that gets handed over to the controller for the normal update, everything is in the right place and there is peace and brotherly love the world over.

Friday, 18 September 2009

redgreen and autoSPEC

Ahhh - the command is autospec, not autotest (RTFM).
Had a problem getting redgreen to work - but commenting out the
require redgreen/autotest inside of ~/.autotest seems to have done the trick

Thursday, 17 September 2009

Rspec

Have put off the day long enough. Got a simple new class to build (address class). Going to build it using rspec from the ground up - not use scaffold etc.
Wish me luck.

Thursday, 27 August 2009

Testing routes

Here is a little tip

have the following in my routes.rb file

map.resources :jobs do |job|
job.resources :pdfs
end


functional test was failing
Couldn't find Job without an ID

So add this to the functional test

get :show, :id =>@pdf, :job_id => @job.id

Passing the job_id puts it in the parameters hash, but not inside the array for the object.

Monday, 24 August 2009

I am starting to hate Factory Girl

Why oh why is it not passing the associated id?
Clearly I am doing something wrong, but wtf is it?

Factory.define :output_type do |f|
f.sequence(:name) {|n| "proofer#{n}"}
f.live true
end


Factory.define :device_type do |f|
f.sequence(:name) {|n| "device_type#{n}"}
f.live true
f.association :output_type
end


Here is the controller test:
test "should create device_type" do
output_type = Factory(:output_type)
@device_types_attr = Factory.attributes_for(:device_type)
assert_difference('DeviceType.count') do
post :create, :device_type => @device_types_attr
end

assert_redirected_to device_type_path(assigns(:device_type))
end



When I run the actual script through a browser and watch the log I get this
Parameters: {"commit"=>"Create", "device_type"=>{"name"=>"testLaser", "live"=>"1", "output_type_id"=>"2"},

But when I run the test, I get this
Parameters: {"device_type"=>{"name"=>"device_type1", "live"=>true}}

ie - no output type is being sent.

Why?
(hmmm - just noticed the live=>true and live=>'1'. Don't suppose that is the problem, but worth checking it out)

Wednesday, 19 August 2009

It works, but I am not sure it is right. Seems very kludgy

have an organisation class, and organisations can be clients, suppliers, printers or prospects.
Want to be able to control this through a form - using check boxes.
The models etc are:
class Client <>
belongs_to :organisation


class Printer <>
belongs_to :organisation



class Organisation <>
has_one :printer
has_one :client


But have had a nightmare sorting out the controller for handling all of this. I am sure there is a better way of doing this.
def update
#get the org type ids
params[:organisation_type_ids] ||= []
#check to se if we have clients etc for those org types
debugger
client = Client.find_by_organisation_id(@organisation.id)
printer = Printer.find_by_organisation_id(@organisation.id)
if params[:organisation_type_ids].length > 0
params[:organisation_type_ids].each do |ot|
case ot.to_i
when 1:
if client.nil?
@organisation.create_client()
end
when 2:
if printer.nil?
@organisation.create_printer()
end
else
end
end
else #none are checked - so get rid of any that exist
if client
@organisation.client.destroy
end
if printer
@organisation.printer.destroy
end
end
#now get rid of any that have been unchecked
#ie client/printer exist but are not in params[:organisation_type_ids]

unless client.nil?
unless params[:organisation_type_ids].include?('1')
@organisation.client.destroy
end
end

unless printer.nil?
unless params[:organisation_type_ids].include?('2')
@organisation.printer.destroy
end
end

It seems the very opposite of DRY (is that wet?) and very, very kludgy. Sure it works, but I am sure that I am failing to understand the power of associations to do the heavy lifting for me.

Tuesday, 18 August 2009

Why testing rocks - and ignore the last one

The polymorphic thing was a dead-end.
Cleared it all out - replaced it with a much more simple arrangement.
K.I.S.S. was never so true.

Love testing. make all the changes, run the test suite and ...

Started
..................................................................
Finished in 5.134175 seconds.

66 tests, 170 assertions, 0 failures, 0 errors