15

got a problem with one to one relations

I have some Matches and i want to have one score for a match.

my Match.rb

has_one :score, :dependent => :destroy

my score.rb

belongs_to :match

my scores_controller.rb

def new
@match = Match.find(params[:match_id])
@score = @match.score.new
end

def create
@match = Match.find(params[:match_id])
@score = @match.score.create(params[:score])
end

my routes.rb

resources :matches do
resources :scores
end

my scores/new.html.haml

= form_for([@match, @match.score.build]) do |f|
    = f.label :score1
    = f.text_field :score1
    %br
    = f.label :score2
    =f.text_field :score2
    %br
    = f.submit

my error that i get

undefined method `new' for nil:NilClass

i haven't worked with one to one relations so far since I'm pretty new to RoR, any suggestions?

EDIT

edited my code to match create_score and build_score, seems to work. but now i have some kind of strange behavior.

in my score.rb

attr_accessible :score1, :score2

but when i try to invoke in my matches/show.html.haml

= @match.score.score1

i get an unknown method call or i don't see anything at all... but if i just call

= @match.score

i get an score object returned (e.g. #)#

EDIT 2

Fix'd problem. I was calling

scores/new.haml.html

= form_for([@match, @match.create_score])

needs to be

= form_for([@match, @match.build_score])

everything works as intended.

needed to enter rails console and fetch those objects to see every :score1 :score2 was nil

cschaeffler
  • 453
  • 3
  • 5
  • 17

3 Answers3

27

Use build instead of new:

def new
    @match = Match.find(params[:match_id])
    @score = @match.build_score
end

Here are the docs for this: http://guides.rubyonrails.org/association_basics.html#belongs_to-build_association

Similarly, in the create method, do it like this:

def create
    @match = Match.find(params[:match_id])
    @score = @match.create_score(params[:score])
end

Docs for this: http://guides.rubyonrails.org/association_basics.html#belongs_to-create_association

Ben Lee
  • 52,489
  • 13
  • 125
  • 145
  • @RyanBigg, I had a typo. Fixed it. – Ben Lee Feb 29 '12 at 12:04
  • well, i see how it works yes. i changed it now so it matches yours and i build_score and i create_score. since create_score saves the object (as mentioned in your lower link) i should be able to call @match.score.score1 (score has attributes :score1, :score2), but I'm not able to call those even when i should be able to go both directions in this relation (declared has_one and belongs_to). error is undefined method `score1' for nil:NilClass – cschaeffler Feb 29 '12 at 18:23
  • @cschaeffler, see the comment I posted on your answer. Your view code can be even simpler. – Ben Lee Feb 29 '12 at 19:12
8

You should be doing match.build_score. This is because when you call the score method it would attempt to fetch the association, and because it's not defined yet, it will return nil. Then you call build on nil and that's why it blows up.

has_many association methods return a sort of "proxy" object to the objects returned by calls to them, so this is why things like posts.comments.build works. The methods for belongs_to and has_one associations attempt to fetch the associations straight off, and so you need to do build_association rather than association.build.

Ryan Bigg
  • 106,965
  • 23
  • 235
  • 261
5

You can create a score by using the below example

@match.build_score
or
@match.create_score
dku.rajkumar
  • 18,414
  • 7
  • 41
  • 58
sangeethkumar
  • 821
  • 1
  • 7
  • 17