2014-09-17 2 views
2

Я использую одного таблицы наследования успешно, как так:Rails 4 STI наследование

class Transaction < ActiveRecord::Base 
    belongs_to :order 
end 

class Purchase < Transaction 
end 

class Refund < Transaction 
end 

сокращенная/упрощена PurchaseController выглядит следующим образом:

class PurchaseController < TransactionController 
    def new 
    @transaction = @order.purchases.new(type: type) 
    end 

    def create 
    @transaction = @order.purchases.new secure_params 
    if @transaction.save 
     redirect_to @order 
    else 
     render :new 
    end 
    end 
end 

сокращенная/упрощенная модель покупки выглядит следующим образом :

class Purchase < Transaction 
    attr_accessor :cc_number, :cc_expiry, :cc_csv 
end 

То, что я пытаюсь сделать есть различные варианты покупки, например покупка наличных денег & покупка чека. Проблема в том, что я не уверен, как назвать модель для этой вариации.

Например:

class Cash < Purchase 
    attr_accessor :receipt_no 
end 

class CashController < TransactionController 
    def new 
    # This will use the Purchase.rb model so that's no good because I need the Cash.rb model attributes 
    @transaction = @order.purchases.new(type: type) 

    # This gives me the following error: 
    # ActiveRecord::SubclassNotFound: Invalid single-table inheritance type: Purchase is not a subclass of Cash 
    @transaction = Cash.new(type: 'Purchase', order: @order.id) 
    end 
end 
+0

серьезные дежавю здесь. – sevenseacat

+0

@sevenseacat, yep не смог его решить. – EasyCo

ответ

1

Я не уверен, почему это не работает для вас, это работает хорошо для меня:

@order.purchases.new(type: "Cash") # returns a new Cash instance 

вы также можете нажать новую Наложенный в ассоциацию, если вы готовы, чтобы сохранить его:

@order.purchases << Cash.new 

Или вы можете определить отдельную ассоциацию в следующем порядке:

class Order < ActiveRecord::Base 
    has_many :cashes 
end 

@order.cashes.new # returns a new Cash instance 
+0

В конце концов, я создал группу разных типов имен. I.e: 'type: Purchase :: Online' &' type: Purchase :: Cash' ... – EasyCo

1

Класс

Возможно, я тупой, но, возможно, вы будете готовы не сделать Purchase тип унаследованный класс?

Проблема, которую я вижу, заключается в том, что вы вызываете Cash.new, когда действительно вам может быть лучше включить все необходимые функции в модели Purchase, после чего она сможет быть переустановлена ​​впоследствии.

В частности, почему вы не просто включить свой собственный type атрибут в модели Purchase, которые вы затем сможете использовать при следующей установке:

#app/controllers/cash_controller.rb 
class CashController < ApplicationController 
    def new 
     @transaction = Purchase.new 
    end 

    def create 
     @transaction = Purchase.new transaction_params 
     @transaction.type ||= "cash" 
    end 

    private 

    def cash_params 
     params.require(:transaction).permit(:x, :y, :z) 
    end 
end 

Единственный недостаток это будет что если вы хотите включить разные business logic для каждого типа покупки, вы все равно захотите использовать свою унаследованную модель. Тем не менее, вы можете просто разделить функциональность в before_create обратного вызова:

#app/models/puchase.rb 
class Purchase < Transaction 
    before_create :set_type 

    private 

    def set_type 
     if type =="cash" 
     # do something here 
     else 
     # do something here 
     end 
    end 
end 

Как таковой, прямо сейчас, я думаю, что ваше использование двух отдельных моделей (Cash и Cheque), вероятно, будет причиной гораздо большей проблемой, чем настоящее время. Хотя мне бы хотелось посмотреть, как вы можете наследовать унаследованный Model, то, что я вам предоставил, вы также можете изучить в

+0

Hey @richpeck, причина, по которой я их разделяю на свои собственные модели, состоит в том, что они имеют разные атрибуты и проверки, и я получаю слишком много условных подтверждений и неиспользуемых атрибутов, если бы я сохранил все это в одной модели. Однако фактические данные, которые сохраняются в базе данных, не зависят от метода покупки.Кроме того, атрибут 'type' зарезервирован для STI для моих двух типов транзакций (' Purchase' & 'Refund'), поэтому мне пришлось бы использовать другое имя атрибута, которое прекрасно, но все начинает запутываться. – EasyCo

Смежные вопросы