A handy one this, for selections that aren't driven from the DB, but which have a value stored in a DB - and yes, I know that is not good practice ...
<%= f.label :number_colours %>
<%= f.select(:number_colours, options_for_select([ ["CMYK", 4], ["Black & white", 1], ["2 colour", 2], ["3 colour", 3], ["CMYK + special", 5] ], :selected=>@page_assembly.number_colours )) %>
the final :selected=> tag allows you to specify which one gets the lucky selected tag...
Thursday, 3 December 2009
Thursday, 26 November 2009
It is times like this I love RoR
Declarative_authorization and Authlogic - just the best. That would have taken me days - as it is it only took as long as it did because upgrading RHEL5 to Ruby 1.8.7 (which DA needs) was such a pain.
Works like a dream in my little test set up - now to make it work on the real thing.
Works like a dream in my little test set up - now to make it work on the real thing.
Wednesday, 25 November 2009
Riiiight ....
Well that was a monumental PITA.
In the end upgrading Ruby caused the gem install to go all haywire. In the end the easiest thing was simply to reinstall all the gems - so now I have two loads of the same gems on my server. Why do I think this is a bad thing and going to come and bite me on my arse someday...?
Of course if RHEL 5 had had the right install of Ruby ...
In the end upgrading Ruby caused the gem install to go all haywire. In the end the easiest thing was simply to reinstall all the gems - so now I have two loads of the same gems on my server. Why do I think this is a bad thing and going to come and bite me on my arse someday...?
Of course if RHEL 5 had had the right install of Ruby ...
Tuesday, 24 November 2009
Grrrr - upgrading Ruby
Why is the YUM package stuck on 1.8.5? Want to use Declarative_Authorization but it needs Ruby >= 1.8.6. Tried to upgrade but the last thing you must do is to end up with two installs of Ruby on yr server. And the last thing I ended up with was ...
That way confusion and madness lie.
So I hope I have managed to uninstall one and upgrade the existing version to 1.8.7. Of course all of this would have been a whole load easier if YUM had had the right package ...
Oh sod it.
Hasn't worked - need to pass it a path I am guessing in the ./configure - path="/usr/bin" I am guessing ...
UPDATE: No - make that prefix=/usr
I read somewhere that that was a no-no and Linus Torvald himself will come and kick my arse for doing that. Hope not.
That way confusion and madness lie.
So I hope I have managed to uninstall one and upgrade the existing version to 1.8.7. Of course all of this would have been a whole load easier if YUM had had the right package ...
Oh sod it.
Hasn't worked - need to pass it a path I am guessing in the ./configure - path="/usr/bin" I am guessing ...
UPDATE: No - make that prefix=/usr
I read somewhere that that was a no-no and Linus Torvald himself will come and kick my arse for doing that. Hope not.
Authlogic
Loving it.
Authentication in zero time - and some quite nifty tracking features right out of the box.
Just followed the tutorial - plus the ever-brilliant Ryan Bates on
Asciicasts and it all worked first time. Have to love it.
Now to work out authorisation...
Authentication in zero time - and some quite nifty tracking features right out of the box.
Just followed the tutorial - plus the ever-brilliant Ryan Bates on
Asciicasts and it all worked first time. Have to love it.
Now to work out authorisation...
Thursday, 12 November 2009
Nested polymorphic associations - 2
Have fought through the undergrowth and am in a clearing - and I can see the way out.
The most important thing is to pay close attention to what
rake routes
tells you. And if you have a job_scannings_batches path - remember to give the objects in the correct order. Rails may be smart, but it isn't that smart.
Have a kludge in place to get the second layer of nesting to work - not sure it is very elegant, but it works. I get the name of the polymorphically associated class and use that to do a custom search
(ie @batchable.Class.name). I can't help but feel I should be able to do it using an association of some kind. However it works so ... (but it feels bad)
The most important thing is to pay close attention to what
rake routes
tells you. And if you have a job_scannings_batches path - remember to give the objects in the correct order. Rails may be smart, but it isn't that smart.
Have a kludge in place to get the second layer of nesting to work - not sure it is very elegant, but it works. I get the name of the polymorphically associated class and use that to do a custom search
(ie @batchable.Class.name). I can't help but feel I should be able to do it using an association of some kind. However it works so ... (but it feels bad)
Wednesday, 11 November 2009
Nested polymorphic associations
My ears are bleeding ...
Slowly getting there, but lordy-oh-lordy nested polymorphism is tricky stuff : things like this
form_for [@job, @batchable, @batch] do |f|
in order to generate the correct form for a URL like this
/jobs/18921/scannings/1/batches/1/edit
We have batches which are either photographic, or scans. They belong to jobs. There is a polymorphic relationship (batchable) between them all.
Then nest all of that inside the jobs so that you only get the batches that belong to a particular job. Fun for all the family...
Slowly getting there, but lordy-oh-lordy nested polymorphism is tricky stuff : things like this
form_for [@job, @batchable, @batch] do |f|
in order to generate the correct form for a URL like this
/jobs/18921/scannings/1/batches/1/edit
We have batches which are either photographic, or scans. They belong to jobs. There is a polymorphic relationship (batchable) between them all.
Then nest all of that inside the jobs so that you only get the batches that belong to a particular job. Fun for all the family...
Wednesday, 4 November 2009
command line svn
Working from home and it is a PITA to get ZigVersion to work so use command line SVN. Most of the time it is fine, but it is a bore when you create a new model and have to add a whole bunch of files by hand.
Some searching found this unix beauty
svn st | grep ^? | awk '{print $2}' | xargs svn add
Haven't tried it - but it looks very sweet indeed.
Tip o' the hat to John Duell on Internet creators
Some searching found this unix beauty
svn st | grep ^? | awk '{print $2}' | xargs svn add
Haven't tried it - but it looks very sweet indeed.
Tip o' the hat to John Duell on Internet creators
Sorting an array - sorted
Had a case where calling in an associated class, but don't seem to be able to determine how Rails sucks the data out of MySql - so have had to sort it after the fact.
This little bit of code seems to do the trick
@jobs.sort! { |a,b| b.id <=> a.id }
This is descending - if you want ascending then swap over b.id and a.id.
Don't ask me what is actually going on - but it works
This little bit of code seems to do the trick
@jobs.sort! { |a,b| b.id <=> a.id }
This is descending - if you want ascending then swap over b.id and a.id.
Don't ask me what is actually going on - but it works
Friday, 30 October 2009
save! and save, update_attributes and update_attributes!
This little bugger ate an hour or so of my day. Had a model with validation on a telephone number field which it should fail if someone puts in letters etc.
For some reason I had changed the update to update_attributes! rather than leaving it as update_attributes (teach you to fiddle with things).
save!/update_attributes!/create! throws an error - and unless you have some way of catching it you will end up with
ActiveRecord::RecordInvalid (Validation failed: Name can't be blank, Name has already been taken, Main number only digits, ., +. (, ), allowed):
instead of the scaffold-like
Let that be a lesson
For some reason I had changed the update to update_attributes! rather than leaving it as update_attributes (teach you to fiddle with things).
save!/update_attributes!/create! throws an error - and unless you have some way of catching it you will end up with
ActiveRecord::RecordInvalid (Validation failed: Name can't be blank, Name has already been taken, Main number only digits, ., +. (, ), allowed):
instead of the scaffold-like
Let that be a lesson
Thursday, 29 October 2009
406 Not Acceptable error on jQuery ajaxSubmit
Doh.
Remember to add format.js to the response block - otherwise it falls over ...
Remember to add format.js to the response block - otherwise it falls over ...
Trick found in find(:all)
What happens if you want to search on an class but by an associated class - so I have a class of printers which are a type of organisation. Organisations have names, printers don't (or rather they do, but they have a name by virtue of being a type of organisation). How do I search on their name?
@printers = Printer.find(:all, :include=>:organisation,
:order=>"organisations.name",
:conditions=>['`organisations`.`name` like ?' , "%#{params[:search]}%"]).paginate( :page => params[:page], :order => 'name')
is how.
Couple of things to note - the :include calls in the associated class - and note the back-ticks (not single quotes) around the field - and also note that it is split in two.
Works like a dream.
@printers = Printer.find(:all, :include=>:organisation,
:order=>"organisations.name",
:conditions=>['`organisations`.`name` like ?' , "%#{params[:search]}%"]).paginate( :page => params[:page], :order => 'name')
is how.
Couple of things to note - the :include calls in the associated class - and note the back-ticks (not single quotes) around the field - and also note that it is split in two.
Works like a dream.
jQuery awsome find
Just about forever I have had a real problem with jQuery inserting elements into the DOM, and then getting events bound to the new inserted items.
It seems (a) I am not alone and (b) this is the archetypal newbie question.
Yes there is a FAQ on this. And guess who didn't read it?
the answer is instead of
$("#link").click(function(){
// whatever
})
You do
$("#link").live("click", function(){
// whatever
})
This is going to change how I do jQuery forever. And I am embarrassed to say that I never knew it. Ho hum.
PS.
Another trick
Getting the text of a the selected value of a pulldown:
It seems (a) I am not alone and (b) this is the archetypal newbie question.
Yes there is a FAQ on this. And guess who didn't read it?
the answer is instead of
$("#link").click(function(){
// whatever
})
You do
$("#link").live("click", function(){
// whatever
})
This is going to change how I do jQuery forever. And I am embarrassed to say that I never knew it. Ho hum.
PS.
Another trick
Getting the text of a the selected value of a pulldown:
$('#categories').find(':selected').text()
Wednesday, 21 October 2009
Tuesday, 20 October 2009
Haven't given up
Just been working on another project.
Complex forms - you have to love them.
Had a problem with having a form updating more than one model - in this case it has to update an address as well.
Devil's own business getting the drop down menu to work - and then found Ryan Bates' comment - I want to marry him ...
Here is the partial to be rendered
<% new_or_existing = address.new_record? ? 'new' : 'existing' %>
<% prefix = "organisation[#{new_or_existing}_address_attributes][]" %>
<% fields_for prefix, address do |address_form| %>
<%= address_form.error_messages %>
<%= address_form.label :address_1 %> <%= address_form.text_field :address_1 %>
<%= address_form.label :address_2 %> <%= address_form.text_field :address_2 %>
<%= address_form.label :address_3 %> <%= address_form.text_field :address_3 %>
<%= address_form.label :town_city %> <%= address_form.text_field :town_city %>
<%= address_form.label :county_state %> <%= address_form.text_field :county_state %>
<%= address_form.label :postcode_zip %> <%= address_form.text_field :postcode_zip %>
<%= address_form.label :country %> <%= address_form.text_field :country %>
<%= address_form.label :live %> <%= address_form.select :live, [['No', false], ['Yes', true]]%>
<% if new_or_existing == 'new' %>
<%=address_form.label :address_type_id %> <%= address_form.collection_select(:address_type_id, AddressType.find_all_by_live(true), :id, :name, {:index=>""}) %>
<% end %>
<% end %>
Then the model is as follows:
def new_address_attributes=(address_attributes)
#handles the address edit form in the edit view
address_attributes.each do |attributes|
addresses.build(attributes)
end
end
def existing_address_attributes=(address_attributes)
addresses.reject(&:new_record?).each do |address|
attributes = address_attributes[address.id.to_s]
if attributes
address.attributes = attributes
else
addresses.delete(address)
end
end
end
def save_addresses
addresses.each do |address|
address.save(false)
end
end
And there is a callback to save the address in the case of an update
after_update :save_addresses
Getting the address_type collection to work was an absolute bugger - it kept rejecting the
organisation[new_address_attributes][]
saying it wasn't allowed. That was when I found Ryan's comment about using the same fields_for thingy and yay - it all works.
Complex forms - you have to love them.
Had a problem with having a form updating more than one model - in this case it has to update an address as well.
Devil's own business getting the drop down menu to work - and then found Ryan Bates' comment - I want to marry him ...
Here is the partial to be rendered
<% new_or_existing = address.new_record? ? 'new' : 'existing' %>
<% prefix = "organisation[#{new_or_existing}_address_attributes][]" %>
<% fields_for prefix, address do |address_form| %>
<%= address_form.error_messages %>
<%= address_form.label :address_1 %> <%= address_form.text_field :address_1 %>
<%= address_form.label :address_2 %> <%= address_form.text_field :address_2 %>
<%= address_form.label :address_3 %> <%= address_form.text_field :address_3 %>
<%= address_form.label :town_city %> <%= address_form.text_field :town_city %>
<%= address_form.label :county_state %> <%= address_form.text_field :county_state %>
<%= address_form.label :postcode_zip %> <%= address_form.text_field :postcode_zip %>
<%= address_form.label :country %> <%= address_form.text_field :country %>
<%= address_form.label :live %> <%= address_form.select :live, [['No', false], ['Yes', true]]%>
<% if new_or_existing == 'new' %>
<%=address_form.label :address_type_id %> <%= address_form.collection_select(:address_type_id, AddressType.find_all_by_live(true), :id, :name, {:index=>""}) %>
<% end %>
<% end %>
Then the model is as follows:
def new_address_attributes=(address_attributes)
#handles the address edit form in the edit view
address_attributes.each do |attributes|
addresses.build(attributes)
end
end
def existing_address_attributes=(address_attributes)
addresses.reject(&:new_record?).each do |address|
attributes = address_attributes[address.id.to_s]
if attributes
address.attributes = attributes
else
addresses.delete(address)
end
end
end
def save_addresses
addresses.each do |address|
address.save(false)
end
end
And there is a callback to save the address in the case of an update
after_update :save_addresses
Getting the address_type collection to work was an absolute bugger - it kept rejecting the
organisation[new_address_attributes][]
saying it wasn't allowed. That was when I found Ryan's comment about using the same fields_for thingy and yay - it all works.
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.
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
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.
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.
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)
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.
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
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
Polymorphic associations make my head hurt
Oh man.
I have an organisation class which has a number of "sub" classes - clients, printers, prospects, suppliers etc. An organisation can have many sub classes (ie an organisation could be simultaneously a client and a supplier for example).
Because clients, printers and prospects are quite different beasts they have to be different classes - not just different instances of the same class - hence the need to have a polymorphic relationship.
Tried to follow Ryan Bates's railscast but it wasn't really working for me.
After playing around with the console to get my head around what is really going on I came up with another way of sorting them out.
Have got the create method to work.
The way I came up with works on the basis that having denoted two classes to have a polymorphic relationship with each other, you can assign an instance of one to the other through the join (and that makes perfect sense ...)
What do I mean by that? Here are the models
My rather kludgy create model uses this:
The create_class method takes a string and returns an instance of that class:
I have a table of classes in the OrganisationType class - which allows me to add new ones dynamically which was my concern with doing everything hardwired - if I want a new sort of polymorphic thing, I can add one quite easily.
Now to sort out the update method, and to write some proper tests to make sure this sucker works in the way I hope it does.
I have an organisation class which has a number of "sub" classes - clients, printers, prospects, suppliers etc. An organisation can have many sub classes (ie an organisation could be simultaneously a client and a supplier for example).
Because clients, printers and prospects are quite different beasts they have to be different classes - not just different instances of the same class - hence the need to have a polymorphic relationship.
Tried to follow Ryan Bates's railscast but it wasn't really working for me.
After playing around with the console to get my head around what is really going on I came up with another way of sorting them out.
Have got the create method to work.
The way I came up with works on the basis that having denoted two classes to have a polymorphic relationship with each other, you can assign an instance of one to the other through the join (and that makes perfect sense ...)
What do I mean by that? Here are the models
class Organisation < ActiveRecord::Baseif I instantiate an organisation object, o, and a client object, c, then by doing o.resource = c, I get the join I am looking for (sets the resource_id and resource_type) correctly.
belongs_to :resource, :polymorphic => true
class Client < ActiveRecord::Base
has_one :organisation, :as => :resource
class Printer < ActiveRecord::Base
has_one :organisation, :as => :resource
My rather kludgy create model uses this:
params[:orgtypes].each do |ot|
@organisation = Organisation.new(params[:organisation])
resource = create_class(OrganisationType.find(ot).name)
resource.save!
@organisation.resource = resource
The create_class method takes a string and returns an instance of that class:
def create_class var
Object.const_get(var).new
end
I have a table of classes in the OrganisationType class - which allows me to add new ones dynamically which was my concern with doing everything hardwired - if I want a new sort of polymorphic thing, I can add one quite easily.
Now to sort out the update method, and to write some proper tests to make sure this sucker works in the way I hope it does.
Friday, 14 August 2009
a sight for sore eyes
Started
................................................................
Finished in 3.983101 seconds.
64 tests, 166 assertions, 0 failures, 0 errors
Unit tests with Factory Girl
Getting the HABTM working was a tricky thing. In the end I had to do this:
def setup
@job = Factory.create(:job)
@version = Factory.build(:version, :job_id =>@job.id)
@printer_set_up = Factory.build(:printer_set_up)
3.times {
pf = Factory.create(:printer_format)
@printer_set_up.printer_formats << page_assembly =" Factory.create(:page_assembly," printer_id =""> @printer_set_up.printer_id, :job_id => @job.id)
end
PrinterFormat and PrinterSetUp both have HABTM relationships with each other.
................................................................
Finished in 3.983101 seconds.
64 tests, 166 assertions, 0 failures, 0 errors
Unit tests with Factory Girl
Getting the HABTM working was a tricky thing. In the end I had to do this:
def setup
@job = Factory.create(:job)
@version = Factory.build(:version, :job_id =>@job.id)
@printer_set_up = Factory.build(:printer_set_up)
3.times {
pf = Factory.create(:printer_format)
@printer_set_up.printer_formats << page_assembly =" Factory.create(:page_assembly," printer_id =""> @printer_set_up.printer_id, :job_id => @job.id)
end
PrinterFormat and PrinterSetUp both have HABTM relationships with each other.
Friday, 31 July 2009
A little thing that saved me
Factory Girl stringify_keys error in Create Test.
Now have to work out why everything else is going wrong ... I think I have to work out how to stop other classes from screwing up the thing I am testing. Sounds like I need stubs and/or mocks. Just have to work out how to use them ...
Now have to work out why everything else is going wrong ... I think I have to work out how to stop other classes from screwing up the thing I am testing. Sounds like I need stubs and/or mocks. Just have to work out how to use them ...
Tuesday, 28 July 2009
redgreen not working
Could not get this bugger to work at all.
After much fiddling around - and a lot of googling, the penultimate comment on here solved it.
There was a lot of talk on sites about edit the .autotest file - but, er, on my install I had three .autotest files - which one to edit?
As it turns out, none of them. I had to make my own in the ~/ directory.
I am using SSH to remote into a RHEL5 box.
did a
$> vim ~/.autotest
got the usual vim type new file thing
and then typed
require 'redgreen/autotest'
yes - that way round, and NOT require 'autotest/redgreen'.
Save that (remembering not to hit Apple-S which sends Vim into a right old state) and at long last glorious living technicolour. Well, red and green at least - oh and amber too.
Second step on the journey of a thousand miles.
Having spent some time trawling around and looking at testing, and following the advice of the ever sagacious Ryan Bates, I think it is worth investing the time and effort in getting a solid test environment built.
To that end it looks like the following
Mocha
RSpec
Cucumber
Webrat
FactoryGirl.
It worries me that that is five packages to try and get working. However, I have got the Unit tests working pretty well so far using fixtures etc.
I think I am going to try and use FactoryGirl rather than fixtures. My brief foray into fixtures was not a happy one. They seem very brittle.
After much fiddling around - and a lot of googling, the penultimate comment on here solved it.
There was a lot of talk on sites about edit the .autotest file - but, er, on my install I had three .autotest files - which one to edit?
As it turns out, none of them. I had to make my own in the ~/ directory.
I am using SSH to remote into a RHEL5 box.
did a
$> vim ~/.autotest
got the usual vim type new file thing
and then typed
require 'redgreen/autotest'
yes - that way round, and NOT require 'autotest/redgreen'.
Save that (remembering not to hit Apple-S which sends Vim into a right old state) and at long last glorious living technicolour. Well, red and green at least - oh and amber too.
Second step on the journey of a thousand miles.
Having spent some time trawling around and looking at testing, and following the advice of the ever sagacious Ryan Bates, I think it is worth investing the time and effort in getting a solid test environment built.
To that end it looks like the following
Mocha
RSpec
Cucumber
Webrat
FactoryGirl.
It worries me that that is five packages to try and get working. However, I have got the Unit tests working pretty well so far using fixtures etc.
I think I am going to try and use FactoryGirl rather than fixtures. My brief foray into fixtures was not a happy one. They seem very brittle.
Monday, 27 July 2009
Factory Girl
Wow - doesn't take long to get pissed off with fixtures, does it? They are incredibly brittle and I spent a load of time hacking fixtures to get them to pass the tests that I knew it would pass. Seemed like a pretty good waste of time.
Soooo - truffling around I found the excellent Ryan Bates had produced a very useful railscast on Factory Girl which seems - one functional test completed - to be a lot better.
I still want to get my head around cucumber and rspec - even shelling out a few bob to buy the book.
It seems very much the right way to go.
Soooo - truffling around I found the excellent Ryan Bates had produced a very useful railscast on Factory Girl which seems - one functional test completed - to be a lot better.
I still want to get my head around cucumber and rspec - even shelling out a few bob to buy the book.
It seems very much the right way to go.
Friday, 24 July 2009
test, test, test
Ok. Have managed (eventually) to get all the Unit tests to pass. That was a very illustrative experience and highlighted some issues - such as not getting all the associations completely nailed.
Funny how a quick "test" in the browser isn't really up to the job at all.
There are some issues with testing callbacks - doesn't seem anyway to pass information to and from the callback.
Now trying to crack the controller tests. The scaffold tests have, so far, failed in rather too many ways.
Not quite sure why this should happen since this is an untouched-by-human-hands object.
We'll find out ...
Funny how a quick "test" in the browser isn't really up to the job at all.
There are some issues with testing callbacks - doesn't seem anyway to pass information to and from the callback.
Now trying to crack the controller tests. The scaffold tests have, so far, failed in rather too many ways.
1) Failure:
test_should_create_brisque_set_up(BrisqueSetUpsControllerTest) [test/functional/brisque_set_ups_controller_test.rb:16]:
"BrisqueSetUp.count" didn't change by 1.
<3> expected but was
<2>.
2) Failure:
test_should_update_brisque_set_up(BrisqueSetUpsControllerTest) [test/functional/brisque_set_ups_controller_test.rb:35]:
Expected response to be a <:redirect>, but was <200>
Not quite sure why this should happen since this is an untouched-by-human-hands object.
We'll find out ...
Monday, 29 June 2009
So far, so good
It is Mao's journey of a thousand miles, it begins with one step. So far, most problems have been resolved by throwing enough time and hard work at them.
The next problem - a recalcitrant radio button that refuses to pick up its value:
there is a field called verhorcut - it is returning the correct value, but so far seem unable to pick up a value for it. In the schema it is a boolean so have tried "0", 0 and "false" but nothing so far.
Keep plodding away.
Next on the agenda - some proper unit testing.
The next problem - a recalcitrant radio button that refuses to pick up its value:
<%= f.label :verhorcut, "horizontal" %> <%= f.radio_button :verhorcut, 0 %>
<%= f.label :verhorcut, "vertical" %> <%= f.radio_button :verhorcut, 1 %>
there is a field called verhorcut - it is returning the correct value, but so far seem unable to pick up a value for it. In the schema it is a boolean so have tried "0", 0 and "false" but nothing so far.
Keep plodding away.
Next on the agenda - some proper unit testing.
Tuesday, 23 June 2009
Everything comes to he who waits
Problem solved. It was behaving very oddly - as if the class didn't really exist properly. Rebuilt the controller and now all works. Hurrah.
Next problem.
Have three classes:
class StoredFile < ActiveRecord::Base
belongs_to :job_store_path
belongs_to :job_set_up
accepts_nested_attributes_for :job_store_path, :allow_destroy => true
class JobSetUp < ActiveRecord::Base
has_many :stored_files
has_many :job_store_paths, :through => :stored_files
accepts_nested_attributes_for :stored_files, :allow_destroy => true
accepts_nested_attributes_for :job_store_paths, :allow_destroy => true
class JobStorePath < ActiveRecord::Base
has_many :stored_files
has_many :job_set_ups, :through => :stored_files
The idea is to generate suggested path names for files, but then store the actual path name so that should the structure change, the old files are not going to be lost.
This works fine:
<% @job_set_up.stored_files.each do |stored_file| %>
<%= content_tag(:strong, stored_file.job_store_path_id) %>
<%=stored_file.address %>
<% end %>
But what I really want is:
stored_file.job_store_path.name - but if I do this I get:
NoMethodError in Job_set_ups#show
Showing app/views/job_set_ups/show.html.erb where line #11 raised:
Ho hum.
Next problem.
Have three classes:
class StoredFile < ActiveRecord::Base
belongs_to :job_store_path
belongs_to :job_set_up
accepts_nested_attributes_for :job_store_path, :allow_destroy => true
class JobSetUp < ActiveRecord::Base
has_many :stored_files
has_many :job_store_paths, :through => :stored_files
accepts_nested_attributes_for :stored_files, :allow_destroy => true
accepts_nested_attributes_for :job_store_paths, :allow_destroy => true
class JobStorePath < ActiveRecord::Base
has_many :stored_files
has_many :job_set_ups, :through => :stored_files
The idea is to generate suggested path names for files, but then store the actual path name so that should the structure change, the old files are not going to be lost.
This works fine:
<% @job_set_up.stored_files.each do |stored_file| %>
<%= content_tag(:strong, stored_file.job_store_path_id) %>
<%=stored_file.address %>
<% end %>
But what I really want is:
stored_file.job_store_path.name - but if I do this I get:
NoMethodError in Job_set_ups#show
Showing app/views/job_set_ups/show.html.erb where line #11 raised:
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.name
Ho hum.
Learning a new language
One of the things I hate most about this is how slooowwwwwwww it is. You know you are going to get there, but boy does it take time.
RoR is proving to be a tricky beast. All that is great about it is also all that is bad. The abstraction is great when it works, but when it doesn't - grrrr.
Having cut my teeth on PHP and writing SQL statements it is so frustrating knowing that you know how to do what you want, but getting the RoR framework to do your bidding is the devil's own business.
Still we will get there.
Currently still grasping at associations. Everytime I think I have got them grasped, they slip through your fingers.
Grappling with a "
NameError in Stored filesController#index
But we'll get there. Have to say loving the console - being able to try stuff out before you buy - lovely.
RoR is proving to be a tricky beast. All that is great about it is also all that is bad. The abstraction is great when it works, but when it doesn't - grrrr.
Having cut my teeth on PHP and writing SQL statements it is so frustrating knowing that you know how to do what you want, but getting the RoR framework to do your bidding is the devil's own business.
Still we will get there.
Currently still grasping at associations. Everytime I think I have got them grasped, they slip through your fingers.
Grappling with a "
NameError in Stored filesController#index
uninitialized constant StoredFilesController::StoredFiles"
But we'll get there. Have to say loving the console - being able to try stuff out before you buy - lovely.
Subscribe to:
Posts (Atom)