0

Some context:

I have some models that look like this

Actor has_many Acts

Act belongs_to Actor, belongs_to Decision

Decision has_many Acts, belongs_to Prompt

Prompt has_many Decisions

What I need to do is in the ActorsController, get a random Prompt that has not been used yet of all the available Prompts.

In my rails app, Actors are presented with prompts that give them a few choices to make. When they make a choice (Decision), that is saved in the db as an Act.

I've tried various iterations of named_scope and find_by_sql, but none worked, and I'm not even sure if my thinking was right to begin with on them, since there are so many models at work, and I don't seem to know where to start.

I hope this gives an idea of what I'm up against. I'd appreciate even a general pointer to form a plan of attack even.

Thanks!

edit

After chewing on this for a couple hours, I've got something working but it's very messy, and my logs are filled with SQL calls, so it could definitely stand a critical eye.

In the Prompt model:

  named_scope :available, lambda { |used| 
    { :conditions => ["id NOT IN (?)", used ] }
  }

In the Actor model:

  def used_prompts
    prompts = Array.new
    if self.acts && self.acts.length >= 1
      self.acts self.acts.each { |act| prompts.insert(0, act.decision.prompt.id) }
      return prompts.sort
    else
      return [0]
    end
  end

And in the ActorsController:

@prompt = Prompt.available(@actor.used_prompts).find(:first, :order => "RAND()")

Obviously the if block in used_prompts is one guilty party here, but I don't know a better way to deal with that since I can't do self.acts.decisions.each or some such thing. Maybe someone can school me :)

John
  • 477
  • 5
  • 13

1 Answers1

0

The simplest thing to do would be to add a after_create or similar callback on the Decision model that marks the associated prompt as used. You could also achieve this using some joins, but that would take a little more work, and will possibly lead to scalability issues (if you care).

Preston Marshall
  • 1,185
  • 1
  • 8
  • 15
  • Thanks for the response Preston. Unfortunately the Prompts will be reused by each separate Actor, so setting a flag on them would cause other issues. You may have a point about scalability though, but I fear I may have already crossed that point :) – John Jan 27 '11 at 13:43
  • Let me try to understand. Your goal is to offer only unselected (by that actor) prompts to the actor? – Preston Marshall Jan 28 '11 at 01:08
  • Correct. The Prompts get recycled for use by other Actors, but any individual Actor should only be given any Prompt once. The prompts are presented during a text-based game, so feeding repeat Prompts makes gameplay somewhat lame. Who wants to be asked the same question 3-5 times out of 15 instances, right? The kids we tested the app on made that quite clear, bless their lack of subtlety :) – John Jan 28 '11 at 03:02