views:

52

answers:

1

Hi everyone,

I have a three-table system: Companies, Customers, and Matches. The matches include, for example, private notes that each party makes about the other and some options they can set regarding the other.

I have two sets of views centered around Companies and Customers for each party to look at the other and modify their notes and settings.

# Customers Controller
def show
  @customer = Customer.find(params[:customer])
  @matchings = @customer.matchings.find... #corrected
  @company = Company.find(params[:company])
end

Obviously the @matchings is incomplete. Given that @matchings has fields customer_id and company_id, how do I find the right matching record? Thank you!

------UPDATE------

That was really helpful, thank you jdl!

The company asks the customer some questions and the customer responds. Questions are stored in Question and answers are stored in MatchingAnswer. To clarify the database's structure:

# models, aggregated
1st set of connections:
  Company has_many :questionlists (QuestionList belongs_to :company)
  QuestionList has_many :questions (Question belongs_to :question_list)
  Question has_many :matching_answers (MatchingAnswer belongs_to :question)
2nd set of connections:
  Company has_many :matchings (Matching belongs_to :company)
  Matching has_many :matching_answers (MatchingAnswer belongs_to :matching)

Remember matching is the 'through' table between Company and Customer. I have to show to the company each question the company has asked and each answer to that question from a particular customer.

# QuestionLists controller
@questions = @questionlist.questions.find(:all)
@matchinganswers = @matching.matching_answers.find(:all, :conditions => ["question_id= ?", @question.id])

...except the condition needs to be satisfied by each question id supplied by my loop INSIDE the view. Let's take a look at the view.

# view
<% @questions.each do |q| %>
  <li><%= q.question %></li>
  <li><% q.matching_answers.each do |a| %>
    <%= a.answer %>
    <% end %></li>
<% end %>

I know this is riddled with holes.. I just haven't been able to fill them properly. How can I do the loop so underneath each question we see the answers the customer gave to that question? Thank you so much guys, this is an amazing group. :)

------UPDATE #2------

The problem is not the nesting, it is that q.matching_answers gives me EVERY answer that every customer has ever given to question q. I need to generate only those matching_answers that both stem from a particular question and match our matching_id (@matching.id). The MatchingAnswer model contains a matching_id field so each answer is unique to that specific match between customer and company. My problem is setting the right parameters so I get only those matching_answers that satisfy:

MatchingAnswer.matching_id = @matching.id
MatchingAnswer.question_id = @question.id

The problem is, while I DO have @matching.id calculated in the QuestionLists controller, I only have access to @question_list (there's only one) and @questions (all the questions belonging to that list). I thought I have to do a loop inside the view that says, for each question, give me those questions that satisfy MatchingAnswer.question_id = [this question.id]. I've been trying to do it with the above nest, but as you can tell, it doesn't give us the two parameters we need.

+2  A: 

Reply to the original question about models.

Your models can do all of this for you, if you set them up correctly.

# company.rb
class Company < ActiveRecord::Base
  has_many :matchings
  has_many :customers, :through => :matchings
end

# customer.rb
class Customer < ActiveRecord::Base
  has_many :matchings
  has_many :companies, :through => :matchings
end

# matching.rb
class Matching < ActiveRecord::Base
  belongs_to :company
  belongs_to :customer
end

Then in your controller, if you have a @customer you can get either the matchings or the companies easily.

@customer = # however you figure out which customer you care about at the moment.
@companies = @customer.companies
@matchings = @customer.matchings

The reverse also works: i.e. @company.customers etc.

If you want to find all Matching objects for a given combination of customer and company, this will do it.

@matchings = Matching.find(:all, :conditions => ["company_id = ? AND customer_id = ?", @company.id, @customer.id])

I have no idea what a @candidate is in your question. I'm assuming that it's a typo.

If you want to clean up your controller a bit, you can push the find logic into a named_scope on Matching.

class Matching < ActiveRecord::Base
  belongs_to :company
  belongs_to :customer

  named_scope :for_company_and_customer, lambda {|comp, cust| {:conditions => {:company_id => comp, :customer_id => cust}}}
end

With this, your code to find matches in the controller once you've found the company and customer would be like this.

@matchings = Matching.for_company_and_customer(@company, @customer)

Reply to the updated question about the views.

I'm assuming that your models are fine now, and you can get the data you need. You should be able to simply nest your HTML lists to get what you're looking for. Obviously, there are fancier ways to do this.

<% @questions.each do |q| %>
  <li><%= h q.question %>
    <ul>
      <% q.matching_answers.each do |a| %>
        <li><%= h a.answer %></li>
      <% end %>
    </ul>
  </li>
<% end %>

(Note the use of the h method. You want to escape user-supplied data to avoid potential security problems.)

jdl