Forum: Ruby on Rails Polymorphic joins work one way, but not the other

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Bd12f94fa674d63098044df707aed1eb?d=identicon&s=25 rubyruy (Guest)
on 2006-02-15 04:42
I've been using polymorphic joins from edge rails based on about 5 lines
of advice Rick Olson gave me over IRC. There's some sparse documentation
popping up but it seems to cover a somewhat different case.

Anyway - I pretty much got it to work - save for one detail. Here's what
I have:

class Event < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true
  #events table has attachable_type and attachable_id fields
end

class Task < ActiveRecord::Base
  has_many :events, :as => :attachable
  #tasks tables is nothing special
end


and now a unit test:

#there's some fixtures above
def test_polymorphics
    assert tasks(:simple_task).events << events(:simple_event_1)
    assert tasks(:simple_task).events << events(:simple_event_2)
    assert events(:simple_event_1).save!
    assert tasks(:simple_task).save!
    assert_equal 2, tasks(:simple_task).events.size
    assert_equal "simple event 1",
tasks(:simple_task).events.find(1).note
    assert_equal "simple task", events(:simple_event_1).task.title
end

All asserts pass except the last one:

ruby test/unit/task_test.rb
Loaded suite test/unit/task_test
Started
E.
Finished in 1.103896 seconds.

  1) Error:
test_polymorphics(TaskTest):
NoMethodError: undefined method `task' for #<Event:0x22258a0>
    _RAILS_ROOT_/config/../vendor/rails/activerecord/lib/active_record/base.rb:1565:in
`method_missing'
    test/unit/task_test.rb:17:in `test_polymorphics'

2 tests, 7 assertions, 0 failures, 1 errors

(path replaced with RAILS_ROOT since I'm secretive like that)

In other words - I can do stuff like @task.events << @event but NOT
@event.task = @task ! (or indeed @event.task.* )  @tasks.events <<
definitely works - I even checked the db and the attachment_type/id
fields are set exactly as expected.

It kind of makes sense - since I never actually mention :tasks anywhere
in Event's model definition. But how exactly do I mention it?

I looked over the example in the wiki but it doesn't seem to touch on
this problem at all (and it kind of tries to do something different too)
- SO - any help is apretiated.

It could also be that this particular piece of functionality simply
hasn't been implemented yet...
821395fe70906c8290df7f18ac4ac6cf?d=identicon&s=25 Rick Olson (Guest)
on 2006-02-15 06:17
(Received via mailing list)
> In other words - I can do stuff like @task.events << @event but NOT
> @event.task = @task ! (or indeed @event.task.* )  @tasks.events <<
> definitely works - I even checked the db and the attachment_type/id
> fields are set exactly as expected.

Try this:

class Event < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true

  def task=(task)
    self.attachable = task
  end
end

If you have a lot of properties, you can earn points towards your
metaprogramming merit badge:

class Event < ActiveRecord::Base
  belongs_to :attachable, :polymorphic => true

  %w(task project stuff).each do |model|
    define_method("#{model}=") do |value|
      self.attachable = value
    end
  end
end

--
Rick Olson
http://techno-weenie.net
Bd12f94fa674d63098044df707aed1eb?d=identicon&s=25 rubyruy (Guest)
on 2006-02-15 07:57
Oh my!  So it isn't implemented!

Are there plans to do so later?

The way you mention only adds the = method right? It won't add all of
task's methods proper from what I can tell.


It would be nice to rework the syntax for the new polymorphic stuff a
little. It's a complicated concept, sure, but it's really a lot less
approachable then the rest of AR-magic.

Here's what I'd like.
class Comment < AR:B
  belongs_to :page, :or => :file, :or => :thing. :or => :other_thing,
:as => :attachable
end

It isn't quite as elegant (since there would have to be an 'implied' :or
=> before :page and :as is actually changing behavior from has_many) but
it would be far more easy to understand imho.

Rick Olson wrote:
>> In other words - I can do stuff like @task.events << @event but NOT
>> @event.task = @task ! (or indeed @event.task.* )  @tasks.events <<
>> definitely works - I even checked the db and the attachment_type/id
>> fields are set exactly as expected.
>
> Try this:
>
> class Event < ActiveRecord::Base
>   belongs_to :attachable, :polymorphic => true
>
>   def task=(task)
>     self.attachable = task
>   end
> end
>
> If you have a lot of properties, you can earn points towards your
> metaprogramming merit badge:
>
> class Event < ActiveRecord::Base
>   belongs_to :attachable, :polymorphic => true
>
>   %w(task project stuff).each do |model|
>     define_method("#{model}=") do |value|
>       self.attachable = value
>     end
>   end
> end
>
> --
> Rick Olson
> http://techno-weenie.net
This topic is locked and can not be replied to.