Radiant 0.6.6 / Rails 2.0 Model Inheritance Question

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

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

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

 :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