Looks like I just sent out an email as HTML. Let's try this again with
plain text...
I'm reworking my Styles and Javascripts Extension to play nice with
Rails 2.0, and incorporate some things that John suggested and I'm
hitting a weird brick wall...
I have a TextAsset Model (with corresponding table) from which I inherit
JavascriptAsset and StylesheetAsset Models (single table inheritance).
I just moved one of my validation rules out of the parent (TextAsset)
into StylesheetAsset and suddenly my tests are failing.
This should be easy but I'm stumped. (This is my first foray into rSpec
but I've basically mimicked the way Radiant is testing it's models).
Help anyone?
Here are the relevant pieces of offending code...
## From stylesheet_asset.rb
class StylesheetAsset < TextAsset
validates_uniqueness_of :name, :message => 'filename already in use'
end
## From stylesheet_asset_spec.rb
require File.dirname(__FILE__) + '/../spec_helper'
describe StylesheetAsset do
scenario :stylesheets
test_helper :validations
before(:each) do
@stylesheet_asset = @model = StylesheetAsset.new(stylesheet_params)
end
...
it 'should validate uniqueness of' do
assert_invalid :name, 'filename already in use', 'main.css' <--
this fails!!!
assert_valid :name, 'just-a-test'
end
end
## From stylesheets_scenario.rb
class StylesheetsScenario < Scenario::Base
def load
create_stylesheet "main.css", :raw_content =>
'body{background:white}'
end
helpers do
def create_stylesheet(name, attributes={})
create_record :stylesheet_asset, name.symbolize,
stylesheet_params(attributes.reverse_merge(:name => name))
end
def stylesheet_params(attributes={})
name = attributes[:name] || unique_stylesheet_name
{
:name => name,
:raw_content => "dummy content"
}.merge(attributes)
end
private
@@unique_stylesheet_name_call_count = 0
def unique_stylesheet_name
@@unique_stylesheet_name_call_count += 1
"stylesheet-#{@@unique_stylesheet_name_call_count}"
end
end
end
What I was hoping to do here was have the two child classes (Javascripts
and Stylesheets) each enforce their own unique naming sets (since
they'll be effectively served from their own directories). This way,
the form validation wouldn't complain if you had both a "my_file"
stylesheet and a "my_file" javascript since they would be served from
/stylesheets/my_file and /javascripts/my_file respectively. (Two
stylesheets or two javascripts with the same name would be a no-no,
though).
Is this some misunderstanding of Single Table Inheritance on my part, a
flaw with Radiant's extension testing, or what?
Thanks for any assistance,
-Chris
on 29.04.2008 00:06
on 29.04.2008 01:27
Chris, Instead of moving it to the child class, I would put the validation in the TextAsset class, but put the scope on the validation to :type, i.e. validates_uniqueness of :name, :scope => :type, :message => 'filename already in use' Sean
on 29.04.2008 16:42
Thanks Sean, I completely forgot about :scope.
This didn't completely fix it for me, though. So, in case this helps
anyone in the future, I still had to change the following...
1. I'm mirroring Radiant's use of:
set_inheritance_column :class_name
instead of using the default Rails 'type' column for single table
inheritance. So of course my code reads:
validates_uniqueness of :name, :scope => :class_name, :message
=> 'filename already in use'
2. This still didn't work, though. And it was only by poking around
the Archive extension that I figured out that the create_record
call in the scenario had to explicitly call out the value for this
class_name field like (shown here in my create_stylesheet helper):
def create_stylesheet(name, attributes={})
create_record :stylesheet_asset,
name.symbolize,
stylesheet_params(attributes.reverse_merge(:name => name,
:class_name => 'StylesheetAsset') )
end
I'm still not sure why #2 was required (possible bug with Scenario
plugin)? I would have thought that creating the record would have
automatically used Rails STI and populated the class name for me.
It's also possible that I wouldn't have needed this if I'd have stuck to
the default STI implementation and just used the 'type' field -- didn't
try that one.
-Chris
on 29.04.2008 16:53
> > :class_name => 'StylesheetAsset') ) > end > > I'm still not sure why #2 was required (possible bug with Scenario > plugin)? I would have thought that creating the record would have > automatically used Rails STI and populated the class name for me. > Ah, that makes sense. Next time you can probably use create_model instead, which creates the actual AR object instead of just writing the record to the DB. Sean