Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Rails 4 has_many through relationship how to add and display data with these relations?

I am working on a rails 4 project where I need to list a users education by school name, degree type and subject type. These are my models:

class UserEducation < ActiveRecord::Base
       belongs_to :school
       belongs_to :subject
       belongs_to :user 
       belongs_to :degree_type
end

class DegreeType < ActiveRecord::Base
      has_many :user_educations
      has_many :users, through: :user_educations
      has_many :subjects, through: :user_educations
      has_many :schools, through: :user_educations

      validates :type, uniqueness: true
end

class Subject < ActiveRecord::Base
  has_many :user_educations
  has_many :users, through: :user_educations
  has_many :schools, through: :user_educations
  has_many :degree_types, through: :user_educations

  validates :name, uniqueness: true
end

class School < ActiveRecord::Base
has_many :user_educations
has_many :users, through: :user_educations
has_many :subjects, through: :user_educations
has_many :degree_types, through: :user_educations

validates :name, uniqueness: true
end

user.rb:

class User < ActiveRecord::Base
       has_many :user_educations
       has_many :schools, through: :user_educations
      has_many :subjects, through: :user_educations
      has_many :degree_types, through: :user_educations

end

and my users controller :

private
  def user_params
      params.require(:user).permit(:about_me, :hobbies, :country,
       :gender, :avatar, :albums, :skill_list, (*What to add here for user education???*)
  end

  def set_user
    @user = User.find_by_profile_name(params[:id])
  end

and my schema:

 create_table "subjects", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "user_educations", force: true do |t|
    t.integer  "user_id"
    t.integer  "school_id"
    t.integer  "subject_id"
    t.integer  "degree_type_id"
    t.integer  "completion_year"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
  add_index "user_educations", ["degree_type_id"], name: "index_user_educations_on_degree_type_id", using: :btree
  add_index "user_educations", ["school_id"], name: "index_user_educations_on_school_id", using: :btree
  add_index "user_educations", ["subject_id"], name: "index_user_educations_on_subject_id", using: :btree
  add_index "user_educations", ["user_id"], name: "index_user_educations_on_user_id", using: :btree

create_table "degree_types", force: true do |t|
    t.string   "type"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

create_table "schools", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

I am not sure how to update the user.params in strong params and how to use a form to input information into these tables as well as how to display the information on the user views page. I have used this rails cast video for some instruction: http://railscasts.com/episodes/196-nested-model-form-part-1.

and have tried this for the user params:

def user_params
  params.require(:user).permit(:about_me, :hobbies, :country,
       :gender, :avatar, :albums, :skill_list,
                               :school_ids => [], 
                               :subject_ids => [], 
                               :degree_type_ids => [])
end

users show:

    <div>User Education:
    <ul>
    <li>School: <%= @user.schools %></li>
    <li>Degree Type: <%= @user.degree_types %></li>
    <li>Subject: <%= @user.subjects %></li>
    <li> Date Completed: <%= @user.user_education.completion_date %></li>
    </ul>
    </div>

users edit:

<%= simple_form_for (@user), :html => { :multipart => true } do |f| %>      
    <%= f.input :about_me %>
    <%= f.input :hobbies %>

    <%= f.input :avatar, as: :file %>
    <%= f.input :country, as: :country, priority: [ "United States of America", "Germany", "United Kingdom", "Canada" ] %>
    <%= f.input :gender, collection: [:male, :female], include_blank: false %>
    <%= f.simple_fields_for :schools do |ff| %>
        <%= ff.input :name, label: "School name" %>
    <% end %> 
    <%= f.simple_fields_for :subjects do |ff| %>
        <%= ff.input :name, label: "Subject name" %>
    <% end %> 
    <%= f.simple_fields_for :degree_types do |ff| %>
        <%= ff.input :type, label: "degree type" %>
    <% end %> 
    <%= f.simple_fields_for :user_educations do |ff| %>
        <%= ff.input :completion_year, label: "Completion Year" %>
    <% end %> 
    <%= f.input :skill_list, label: "Skill list seperate by comma" %>
    <div class="form-actions">
       <%= f.button :submit %>
    </div>
<% end %>

this is my output on the show page after completing the form:

School: #<School::ActiveRecord_Associations_CollectionProxy:0x0000000531ba00> Degree Type: #<DegreeType::ActiveRecord_Associations_CollectionProxy:0x00000005319048> Subject: #<Subject::ActiveRecord_Associations_CollectionProxy:0x00000004ec3700> Date Completed: #<UserEducation::ActiveRecord_Associations_CollectionProxy:0x00000004eb8800>

Can you please explain what is happening and help remedy this problem? Thanks

Jason Seifer Maciej Czuchnowski David Moore Alexander Batalov John Steer-Fowler

2 Answers

Could you please share your code from controllers how do you create users, the 'create' and 'new' methods from controllers. Or could you share gitHub repo, with us? I'd like to help :)

https://github.com/Tyler8oliver/ProjectCollabo/tree/to/Education3 here is a link to the current repo. I am currently working of the to/Education3 branch. I think this is a problem with my lack of understanding of Activerecords Query system and I am trying to figure out how join tables in has_many through relations work.

Also what is the difference between has_many through and has_and_belongs_to_many? In my example which would be more appropriate?

I'm not sure in my skills to be accurate enough to provide such advice in software architecture. As for me, when it's time to think about relationships between models there is an awesome guide: 2.8 Choosing Between has_many :through and has_and_belongs_to_many Please check it, it's very helpful.

Ok, O fixed one bug: In your app/views/users/show.html.erb it shows School: #<School::ActiveRecord_Associations_CollectionProxy:0x0000000531ba00> because it is a collection. If you handle it like

<% @user.schools.each do |school| %>
  <%= school.name %>
<% end %>

than it works fine. The next thing to fix is that it doesn't update or create Schools... Also I found this in logs:

Unpermitted parameters: schools, subjects, degree_types, user_educations

Look through your mechanics of how you creating and updating Schools, Subjects and Degree Types. When figure this out will post the solution here.

Hope it helps.

Ok that brings like to the collection bug. Could the user education instance be: @user_education = User_education.where (:user _id => @user) then from there assign the others?