views:

38

answers:

1

I have a list of 'Interests' that each user in my system has the ability to rate. An admin can add/remove Interests at any time. When the user goes to edit their account, I want to show a list of all the Interests in the system, and a drop down with a 1..5 value. I am wondering how I set this up..

Using accepts_nested_attributes for doesn't seem to work because when I use a field_for it wants to create the form for each of the Interests that have been saved. What I want is for each of the interests to show up, and on save, if the user has rated the interest before, it updates the value, if it has not been rated before, then add a new entry.

Currently a User:

  has_many :user_interests, :dependent => :destroy
  has_many :interests, :through => :user_interests, :foreign_key => :user_id  

  accepts_nested_attributes_for :user_interests

Currently a UserInterest:

  belongs_to :user
  belongs_to :interest

Currently an Interest:

  has_many :user_interests, :dependent => :destroy
  has_many :users, :through => :user_interests, :foreign_key => :interest_id, :dependent => :destroy
A: 

I ended up just flipping the loops, so it was looping through the interests first, then creating the form element for each.

<% Interest.all.group_by(&:interest_category).each do |category, interests| %>
    <p>
        <h4 id="interests"><%= category.title %></h4>
        <ul>
            <% interests.each do |interest| %>
            <% user_interest = @current_user.user_interests.find_by_interest_id(interest) || @current_user.user_interests.new(:interest_id => interest.id) %>
                <% form.fields_for "user_interests[#{interest.id}]", user_interest do |user_interests_form| %>
                    <li><%= user_interests_form.select :rating, options_for_select([1, 2, 3, 4, 5], user_interest.rating || ""), {:prompt => "-- Select One --"} %> <%= interest.title %></li>
                <% end %>
            <% end %>
        </ul>
    </p>
    <% end %>

And creating a custom setter for the interests after the form was submitted.

  def user_interests=(interests)
    interests.each do |interest|
      interest_id = interest[0]
      rating = interest[1]["rating"]

      # confirm that a rating was selected
      if rating.to_i > 0
        # see if this user has rated this interest before
        int = self.user_interests.find_by_interest_id(interest_id)

        # if not, build a new user_interest for this interest
        int = self.user_interests.build(:interest_id => interest_id) if int.nil? 

        # set the rating
        int.rating = rating

        # save the new user_interest, or update the existing one
        int.save
      end
    end
  end
Rabbott