Working on a simple example of double sided polymorphic relationships using the has_ many_ polymorphs ActiveRecord plugin. I have two classes, "cats" and "dogs", which can have "friendships" with each other, so three classes in all: "cats", "dogs" and "friendships". A cat can be friends with a dog (yes, it does happen!) and of course also with other cats. The same goes for dogs. Here are my models:
class Cat < ActiveRecord::Base
validates_presence_of :name
end
class Dog < ActiveRecord::Base
validates_presence_of :name
end
class Friendship < ActiveRecord::Base
belongs_to :left, :polymorphic => true
belongs_to :right, :polymorphic => true
acts_as_double_polymorphic_join(
:lefts => [:cats, :dogs],
:rights => [:dogs, :cats]
)
end
I've been trying for days to get this to work and I must be missing something obvious. When I try to create a new friendship I get:
NameError (wrong constant name cats):
(eval):7:in `before_save'
app/controllers/friendships_controller.rb:45:in `create'
or
NameError (wrong constant name dogs):
(eval):7:in `before_save'
app/controllers/friendships_controller.rb:45:in `create'
This is my schema.rb:
ActiveRecord::Schema.define(:version => 20090613051350) do
create_table "cats", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "dogs", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "friendships", :force => true do |t|
t.integer "left_id"
t.string "left_type"
t.integer "right_id"
t.string "right_type"
t.datetime "created_at"
t.datetime "updated_at"
end
end
I am trying to create a new "friendship" by making a POST to, for example, /cats/3/relationships with a route that gets left_ type and left_ id from the URL and the right_ type and right_ id from the POST parameters. The routing triggers the #create method of the friendships_ controller correctly and the resulting params look like this:
Parameters: {
"authenticity_token"=>"gG1eh2dXTuRPfPJ5eNapeDqJu7UJ5mFC/M5gJK23MB4=",
"left_type"=>"cats",
"right_type"=>"dogs",
"left_id"=>"3",
"right_id"=>"1"
}
For reasons that are outside the scope of this question I want to separate between "lefts" and "rights" in such a way that I can keep track of to whom the friendship was POSTed (hence the "lefts" and "rights"), but perhaps my model is not the right way to accomplish this? Have I misunderstood the purpose of the has_ many_ polymorphs plugin? Here is the #create action from friendships_ controller:
def create
@friendship= Friendship.new(
:left_type => params[:left_type],
:left_id => params[:left_id],
:right_type => params[:right_type],
:right_id => params[:right_id]
)
respond_to do |format|
if @friendship.save
format.xml {
render :xml => @friendship,
:status => :created,
:location => @friendship
}
else
format.xml {
render :xml => @friendship.errors,
:status => :unprocessable_entity
}
end
end
end
And finally my routes.rb:
map.resources :friendships
map.resources :cats do |cat|
cat.resources :friendships, :path_prefix => "/:left_type/:left_id"
end
map.resources :dogs do |dog|
dog.resources :friendships, :path_prefix => "/:left_type/:left_id"
end
Like I said, I've spent a long time on my own to try to figure this out but the documentation that exists is either outdated, too general or too advanced - or, in some cases, all three at the same time. It is not easy to get started on this RoR stuff, I can tell you! I know there are som real benefits of RoR proficiency so I will persist, but some of these headscratchers are so bad I'm starting to get a bald patch. I know there are a lot of experienced Ruby/Rails devs out there and I'm hoping someone can come out of the woodwork and explain this here thingy for us mere mortals.
Thanks in advance,
JS