Это, вероятно, больше проблем, чем стоит, и опасно, потому что включает в себя переопределение initialize
метода класса Credit
, но я думаю, что это может сработать.Я бы посоветовал вам попробовать решение, которое я предложил ранее, и отбросить эти драгоценные камни или изменить их, чтобы они могли использовать ваш метод.При этом здесь ничего не говорится:
Сначала вам нужно найти способ вызова метода для инициализатора Credit.Давайте используем класс , который я нашел в сети и который называется CallChain
, но мы изменим его для наших целей.Возможно, вы захотите поместить это в папку lib
.
class CallChain
require 'active_support'
def self.caller_class
caller_file.split('/').last.chomp('.rb').classify.constantize
end
def self.caller_file(depth=1)
parse_caller(caller(depth+1).first).first
end
private
#Stolen from ActionMailer, where this was used but was not made reusable
def self.parse_caller(at)
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
end
Теперь нам нужно перезаписать инициализатор классов Credit
, потому что когда вы делаете вызов Credit.new
или Credit.create
из другогокласс (в данном случае ваш Image
класс), он вызывает инициализатор из этого класса.Вам также необходимо убедиться, что при вызове Credit.create
или Credit.new
, который вы вводите :caller_class_id => self.id
в аргумент атрибутов, поскольку мы не можем получить его из инициализатора.
class Credit < ActiveRecord::Base
#has a field called name
has_many :images
attr_accessor :caller_class_id
def initialize(args = {})
super
# only screw around with this stuff if the caller_class_id has been set
if caller_class_id
caller_class = CallChain.caller_class
self.send(caller_class.to_param.tableize) << caller_class.find(caller_class_id)
end
end
end
Теперь, когда у нас есть эта настройка, мы можем сделать простой метод в нашем классе Image
, который создаст новый Credit
и правильно настроит ассоциацию следующим образом:
class Image < ActiveRecord::Base
belongs_to :credit
accepts_nested_attributes_for :credit
# for building
def build_credit
Credit.new(:attr1 => 'val1', etc.., :caller_class_id => self.id)
end
# for creating
# if you wanted to have this happen automatically you could make the method get called by an 'after_create' callback on this class.
def create_credit
Credit.create(:attr1 => 'val1', etc.., :caller_class_id => self.id)
end
end
Опять же, я бы действительно не хотелНе рекомендую, но я хотел посмотреть, возможно ли это.Попробуйте, если вы не против переопределить метод initialize
для Credit
, я считаю, что это решение, которое соответствует всем вашим критериям.