2013-07-06 3 views
2

Как я могу это решить? Повторно инициализировать рубин Класс

class Person 
end 

class Person < ActiveRecord::Base 
end 

TypeError: superclass mismatch for class Person. 


Я хочу переинициализировать класс.

+2

Я думаю, что вы должен объяснить вашу проблему немного больше. Вы определяете класс оба раза? – NicoSantangelo

+0

Да. Я хочу изменить класс, который я объявляю раньше. Возможно, существует некоторое решение с свободной памятью. Я думаю, что это может решить мою проблему с ActiveRecord http://stackoverflow.com/questions/17506860/bug-with-activerecords – iiylll

+0

Allpodo, я ненавижу говорить об этом, но мой ответ (хотя и правильный) является грязным взломом и является крайне маловероятно, чтобы решить вашу проблему. Вы должны использовать более четкие имена классов и имена таблиц. ActiveRecord определяет соглашение, которое связывает ваше имя класса с именем вашей таблицы, которое вы можете переопределить, если хотите. Возможно, вам придется перезапустить каждый процесс сервера Rails после удаления этих таблиц и «перезагрузить!» В консоли rails. – user1158559

ответ

2

Вы можете (сорт) сделать это.

# initial definition 
class Person 
end 

# new definition 
class OverridePerson < ActiveRecord::Base 
end 

Person = OverridePerson 
  • Пожалуйста, смотрите комментарий по Маршаллу @ Андрей. Можно вернуть Person, а затем определить его, не создавая фиктивную класс OverridePerson

Сходства к тому, что вы хотите сделать:

  • Person будет относиться к новому классу

Differences, что вы хочу сделать:

  • Существующие экземпляры не изменят свои кланы ы
  • методы класса и переменные будут затерт
  • Person.name будет OverridePerson, но вы можете переопределить, что быть "Person"

случаев использования может быть:

  • redefine Person, duck-typing, чтобы обмануть библиотеку или приложение. ИМО это совершенно законно для целей тестирования, хотя ActiveRecord :: Base будет сложным для утиного типа. Я рекомендую использовать FockAR или RSpec mocks или заглушки в исходном классе

  • Вы хотите создать класс под названием Person, но он уже определен. В этом случае я рекомендую пространство имен внутри модуля.

+0

Ухм, ты тоже получил объяснение без объяснения, это странно ... – NicoSantangelo

+0

Да ... Ах, кто бы это ни был, только один раз! Не стесняйтесь расширять мой ответ. – user1158559

+0

Я также рекомендую изучать рубиновые версии 2.0, где вы можете обезглавить патч класса, но выберите, где вы делаете доступными обезьяны. – user1158559

6

Как только вы создали класс в рубине, вы не сможете изменить свой суперкласс, открыв его снова. Вот почему вы получаете ошибку TypeError: superclass mismatch for class Person..

Другие ответы предоставили альтернативы, но важно отметить, что ни один из них не изменяет существующий класс Person, но на самом деле создает новый класс и переназначает старую константу Person новому классу в рамках ограничений, уже заявленных @ user1158559 в его ответе.

+0

+1, хотя это не совсем ответ. Но я думаю, что это хорошо, как «голос разума». Изменение суперкласса - плохая идея. – Kelvin

+0

Мне нравится думать, что это answerr в том смысле, что он разъясняет, что то, что OP хочет сделать, фактически невозможно. Другие ответы, в том числе и принятые, предоставляют альтернативы, которые не решают точной проблемы, но могут быть полезны в разных сценариях, хотя то, почему кто-то захочет это сделать, выходит за рамки моего понимания. В любом случае, спасибо за рассмотрение этого вопроса ответ, достойный upvote @Kelvin =) – Cezar

2

Просто убедитесь, что вы используете одну и ту же подпись класса каждый раз.

class Person < ActiveRecord::Base 
    def x 
    end 
end 


class Person < ActiveRecord::Base 
    def y 
    end 
end 
+0

Еще лучше, если у вас есть автозагрузка, а «Лицо» - это модель, просто ссылку «Лицо», чтобы убедиться, что исходное определение автоматически загружено из 'app/models/person.rb'. Затем снова откройте определение класса без дополнительной ссылки на суперкласс. – user1158559

+1

Кроме того, указание суперкласса каждый раз не очень суровое и ненужное, если вы можете гарантировать порядок загрузки. – user1158559

+0

@ user1158559 если 'Person' - это модель рельсов, она будет загружена, когда вы ее используете. В противном случае просто «требуется» из кода, который ему нужен. – Kelvin

0

Это не может быть ответом вы искать, но его путь к undefine a class или константу, так что вы можете переопределить его, но он потеряет все оригинальные методы:

Object.send(:remove_const, :Person) 
Смежные вопросы