David Harbage
David Harbage

Reputation: 697

How to access id in model

I have a user class, which has_many resumes, each of which has many items. On my users/show page, I render multiple resumes, which is working. In my users_controller I have the following:

def show
 ...
 @resumes = @user.resumes.paginate(page: params[:page])
 @resume = @user.resumes.build if user_signed_in?
 @resume_items = @user.res.paginate(page: params[:page])
 @edu_items = @resume.edu.paginate(page: params[:page])
 ...
end

I defined the function res in my User model:

def res
  Resume.where("student_id = ?", id)
end

And that worked quite well. However, I'm trying to do the same thing with the function edu in my Resume model:

def edu
  Education.where("resume_id = ?", id)
end

but it's not working, @edu_items isn't being set to anything. Now I know it has to do with this method specifically, because if I change id to the id of a specific resume, that resume's items are rendered correctly, except across every resume. I know it's a simple fix, I've just been staring at it for way too long at this point and can't figure it out. Any advice would be amazing.

EDIT: @makaroni4: Instead of having @educations = @user.educations, I'd rather keep the items from each resume separate. Is it possible to define a method like the educations one that will make @educations = @resume.educations?

EDIT 2: I managed to get what I was trying to do to work, thanks for the advice. I solved it by doing away with the edu method altogether, and passing local variables to the partial:

  <%= render :partial => 'shared/edu', :as => :educations, :locals => {:resume_educations => resume_item.educations} %>

shared/edu

<% if resume_educations.any? %>
   <ol class="educations">
     <%= render partial: 'shared/edu_item', collection: resume_educations %>
   </ol>
   <%= will_paginate @educations %>
<% end %>

Probably not the cleanest solution, but it seems to work.

Upvotes: 0

Views: 2199

Answers (2)

makaroni4
makaroni4

Reputation: 2281

I think that your model structure should look like:

class User < ActiveRecord::Base
  has_many :resumes

  def educations
    Education.joins(:resume => :user).where(:users => { :id => id })
  end
end

class Resume < ActiveRecord::Base
  belongs_to :user
  has_many :educations
end

class Education < ActiveRecord::Base
  belongs_to :resume
end

So in your controller you can access them like:

@resumes = @user.resumes
@educations = @user.educations # all users educations, from all resumes

or

@educations = @resume.educations # educations for particular resume

And also I recommend you to read this article http://petdance.com/2012/04/the-worlds-two-worst-variable-names/ about variables naming, variables like resume_items and methods res and edu should say that you're doing smtg not in the right way.

Upvotes: 3

Mischa
Mischa

Reputation: 43298

It does not work, because the result of your edu method will always be empty.

In your code you are building a resume object:

@resume = @user.resumes.build if user_signed_in?

If you use build an object is created, but not saved to the database yet. This means that your @resume.id is nil. And thus the result of your edu method will be empty.

You could use the following to create the record in the database:

@resume = @user.resumes.create if user_signed_in?

But your edu method will still return an empty collection, because it's a new record and it won't be associated with any items yet.

Please expand on what you are trying to do exactly, because with this code @resume.edu will always be empty for the reason explained above.

Also: consider using the built-in Rails functionality instead of making your own methods.

Upvotes: 1

Related Questions