title: Scopes and Queries with Polymorphic Associations
body: <p>I have found very little about how one can write scopes for polymorphic associations in rails, let alone how to write queries on polymorphic associations.  </p>
  
  <p>In the Rails Documentation, I have looked at the <a href="http://guides.rubyonrails.org/association_basics.html#polymorphic-associations" rel="noreferrer">Polymorphic Associations section</a>, the <a href="http://guides.rubyonrails.org/active_record_querying.html#joining-tables" rel="noreferrer">Joining Tables section</a>, and the <a href="http://guides.rubyonrails.org/active_record_querying.html#scopes" rel="noreferrer">Scopes section</a>.  I have also done my fair share of googling.</p>
  
  <p>Take this setup for example:</p>
  
  <pre><code>class Pet &lt; ActiveRecord::Base
    belongs_to :animal, polymorphic: true
  end
  
  class Dog &lt; ActiveRecord::Base
    has_many :pets, as: :animal
  end
  
  class Cat &lt; ActiveRecord::Base
    has_many :pets, as: :animal
  end
  
  class Bird &lt; ActiveRecord::Base
    has_many :pets, as: :animal
  end
  </code></pre>
  
  <p>So a <code>Pet</code> can be of <code>animal_type</code> "Dog", "Cat", or "Bird".</p>
  
  <p>To show all the table structures: here is my <strong>schema.rb</strong>:</p>
  
  <pre><code>create_table "birds", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
  
  create_table "cats", force: :cascade do |t|
    t.integer  "killed_mice"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end
  
  create_table "dogs", force: :cascade do |t|
    t.boolean  "sits"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
  
  create_table "pets", force: :cascade do |t|
    t.string   "name"
    t.integer  "animal_id"
    t.string   "animal_type"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end
  </code></pre>
  
  <p>I then went ahead and made some records:</p>
  
  <pre><code>Dog.create(sits: false)
  Dog.create(sits: true)
  Dog.create(sits: true) #Dog record that will not be tied to a pet
  Cat.create(killed_mice: 2)
  Cat.create(killed_mice: 15)
  Cat.create(killed_mice: 15) #Cat record that will not be tied to a pet
  Bird.create
  </code></pre>
  
  <p>And then I went and made some <code>pet</code> records:</p>
  
  <pre><code>Pet.create(name: 'dog1', animal_id: 1, animal_type: "Dog")
  Pet.create(name: 'dog2', animal_id: 2, animal_type: "Dog")
  Pet.create(name: 'cat1', animal_id: 1, animal_type: "Cat")
  Pet.create(name: 'cat2', animal_id: 2, animal_type: "Cat")
  Pet.create(name: 'bird1', animal_id: 1, animal_type: "Bird")
  </code></pre>
  
  <p>And that is the setup!  Now the tough part: I want to create some scopes on the <code>Pet</code> model which dig into the polymorphic associations.  </p>
  
  <p>Here are some scopes I would like to write:</p>
  
  <ul>
  <li>Give me all the <code>Pets</code> of animal_type == "Dog" that can sit</li>
  <li>Give me all the <code>Pets</code> of animal_type == "Cat" that have killed at least 10 mice</li>
  <li>Give me all the <code>Pets</code> that are NOT both animal_type "Dog" and cannot sit.  (In other words: Give me all the pets: all of them: except for dogs that cannot sit)</li>
  </ul>
  
  <p>So in my <code>Pet</code> model I would want to put my scopes in there:</p>
  
  <pre><code>class Pet &lt; ActiveRecord::Base
    belongs_to :animal, polymorphic: true
  
    scope :sitting_dogs, -&gt; {#query goes here}
    scope :killer_cats, -&gt; {#query goes here}
    scope :remove_dogs_that_cannot_sit, -&gt; {#query goes here} #only removes pet records of dogs that cannot sit. All other pet records are returned
  end
  </code></pre>
  
  <p>I am finding it pretty tough to write these scopes.  </p>
  
  <p>Some stuff I found online makes it look like you can only write these scopes with raw SQL.  I am wondering if it is possible to use the Hash syntax for these scopes instead.</p>
  
  <p>Any tips/help would be greatly appreciated!</p>