Forum: Ruby on Rails Trouble with composed_of

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.
Pat M. (Guest)
on 2006-03-19 08:29
(Received via mailing list)
I'm trying to use composed_of within my model.  I have a field in my
database named 'card1', which is simply a string.  I have this in my
model

class Player < ActiveRecord::Base
  composed_of :card1, :class_name => 'Card'
end

class Card
  attr_reader :value, :suit

  def initialize(s)
    @value = s[0].chr
    @suit = s[1].chr
  end
end

The accessor method works fine..in my fixture I have a Player created
with card1: As, and I can do
players(:first).card1.suit  #  => 's'

But I can't assign it:
players(:first).card = nil

Causes
NoMethodError: You have a nil object when you didn't expect it!
The error occured while evaluating nil.card1
    (eval):3:in `card1='
    test/unit/player_test.rb:51:in `test_validate_cards'

There is no validation for card1 in the Player class.  For some reason
I simply can't assign card1.  What am I doing wrong?

Pat
Tom M. (Guest)
on 2006-03-19 13:17
(Received via mailing list)
On Mar 18, 2006, at 10:04 PM, Pat M. wrote:

>
> But I can't assign it:
> players(:first).card = nil

I think that should be:

players(:first).card1 = nil

I'm sort of guessing that's an email typo, though.

I wouldn't be surprised if composed_of assignment
expects a composed_of object on assignment, i.e.
it wants to assign a Card object, not a nil object.

--
-- Tom M.
Pat M. (Guest)
on 2006-03-19 13:17
(Received via mailing list)
On 3/19/06, Tom M. <removed_email_address@domain.invalid> wrote:
> > class Card
> > players(:first).card1.suit  #  => 's'
> I wouldn't be surprised if composed_of assignment
>
Yeah, that's just an email typo.  Anyway, setting it to a Card object
isn't any better..
players(:first).card1 = Card.new 'Jd'

results in
  1) Error:
test_validate_cards(PlayerTest):
NoMethodError: undefined method `card1' for #<Card:0x227263c
@suit="d", @value="J">
    (eval):3:in `card1='
    test/unit/player_test.rb:51:in `test_validate_cards'

It's obviously parsing the suit and rank fine..I don't understand what
the problem is.

Pat
Pat M. (Guest)
on 2006-03-19 18:27
(Received via mailing list)
On 3/19/06, Pat M. <removed_email_address@domain.invalid> wrote:
> > >
> > > with card1: As, and I can do
> >
> > http://lists.rubyonrails.org/mailman/listinfo/rails
> @suit="d", @value="J">
>     (eval):3:in `card1='
>     test/unit/player_test.rb:51:in `test_validate_cards'
>
> It's obviously parsing the suit and rank fine..I don't understand what
> the problem is.
>
> Pat
>

I've kind of gotten around it..I made another attribute in the Card
class named create_str, and did the mapping as
composed_of :card1, :class_name => 'Card', :mapping => %w(card1
create_str)

The Card class looks like
class Card
  attr_reader :suit, :rank, :create_str

  def to_s
    "#{@rank}#{@suit}"
  end

  def initialize(create_str)
    @create_str = create_str

    @rank = create_str[0].chr
    @suit = create_str[1].chr
  end
end

I still can't set card1 to nil though.  I want to be able to make it
nil though, so I'm not really sure what to do.

composed_of looked like it's what I needed, but I'm basically unable
to figure it out..

Pat
Pat M. (Guest)
on 2006-03-19 18:47
(Received via mailing list)
On 3/19/06, Pat M. <removed_email_address@domain.invalid> wrote:
> > > > end
> > > > The accessor method works fine..in my fixture I have a Player created
> > > I'm sort of guessing that's an email typo, though.
> > > removed_email_address@domain.invalid
> > NoMethodError: undefined method `card1' for #<Card:0x227263c
> I've kind of gotten around it..I made another attribute in the Card
>
>
> composed_of looked like it's what I needed, but I'm basically unable
> to figure it out..
>
> Pat
>

Well here's my solution.  It's kind of ugly and it bugs me that it's
so un-Railsy..but I don't know of a better way.  I'd appreciate input
from anyone else.

Pat


  def card1
    if self[:card1].nil? || self[:card1] == ''
      nil
    else
      @card1_card ||= Card.new self[:card1]
    end
  end

  def card1=(c)
    @card1_card = c
    self[:card1] = "#{c}"
  end

  def card2
    if self[:card2].nil? || self[:card2] == ''
      nil
    else
      @card2_card ||= Card.new self[:card2]
    end
  end

  def card2=(c)
    @card2_card = c
    self[:card2] = "#{c}"
  end
This topic is locked and can not be replied to.