ruby on rails, has_many, define class name for polymorphic relationship
Asked Answered
U

3

6

This is my code for moving data from my old database:

class Old < ActiveRecord::Base
  establish_connection :old_version
  self.abstract_class = true

  class Recipe < self
    set_table_name :recipes
    has_many :uploaded_files, :as => :storage
  end

  class UploadedFile < self
    set_table_name :uploaded_files
    belongs_to :storage, :polymorphic => true
  end
end

When I run the following code

Old::Recipe.all.each do |recipe|
  puts recipe.uploaded_files.to_sql
end

It performs this SQL

SELECT `uploaded_files`.* FROM `uploaded_files`  WHERE `uploaded_files`.`storage_id` = 38 AND `uploaded_files`.`storage_type` = 'Old::Recipe'

The problem is that I get:

`storage_type` = 'Old::Recipe'

But I need:

`storage_type` = 'Recipe'

How can I change the class for a polymorphic relationship?

The doc for has_many doesn't give me an answer.

Uredo answered 10/4, 2012 at 5:43 Comment(2)
is there a reason why the Recipe class is nested inside the Old class?Ptarmigan
Perhaps this was moved into a Rails Engine @pixeltrix. Anyone have a better answer for this?Radiothermy
S
9

Recently I had similar problem, this is a solution that worked for me in rails 4.2:

class Recipe < self
  set_table_name :recipes
  has_many :old_files, -> (object) { unscope(where: :storage_type).where(storage_type: 'Recipe') }, class_name: 'UploadedFile'
end

You have to add unscope(:where) to remove condition uploaded_files.storage_type = 'Old::Recipe' from query.

Slut answered 20/5, 2015 at 11:42 Comment(1)
this worked for me, but still needs as: :storageVinnie
A
3

The answer by santuxus above is working properly for rails 4.2+

However, for lower versions, you could try overwriting the association like so:

class Recipe
  has_many :uploaded_files, conditions: { storage_type: 'Recipe' }, foreign_key: :storage_id
end
Affricative answered 26/3, 2019 at 10:0 Comment(0)
U
0

Unfortunately, for now I found only one way to do that:

class Old < ActiveRecord::Base
  establish_connection :old_version
  self.abstract_class = true

  class Recipe < self
    set_table_name :recipes
    has_many :old_files,
             :class_name => 'UploadedFile',
             :finder_sql => Proc.new {
                %Q{
                  SELECT uploaded_files.*
                  FROM   uploaded_files
                  WHERE  uploaded_files.storage_id = #{id} AND
                         uploaded_files.storage_type = 'Recipe'
                }
              }
  end

  class UploadedFile < self
    set_table_name :uploaded_files
    belongs_to :storage, :polymorphic => true
  end
end


namespace :old do
  task :menu => :environment do
    Old::Recipe.all.each do |recipe|
      puts '~' * 50
      puts recipe.id
      recipe.old_files.to_a.each do |file|
        puts file.storage_id, file.storage_type
      end
    end
  end
end

very very sad

Uredo answered 10/4, 2012 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.