Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 API - Accepts nested attribute for namespaced model

I have something like this:

module Api
  module V1
    class Order < ActiveRecord::Base

    has_many :order_lines
    accepts_nested_attributes_for :order_lines
  end
end

module Api
  module V1
    class OrderLine < ActiveRecord::Base

    belongs_to :order
  end
end

In my orders controller, I permit the order_lines_attributes param:

params.permit(:name, :order_lines_attributes => [
                      :quantity, :price, :notes, :priority, :product_id, :option_id
            ])

I am then making a post call to the appropriate route which will create an order and all nested order_lines. That method creates an order successfully, but some rails magic is trying to create the nested order_lines as well. I get this error:

Uninitialized Constant OrderLine.

I need my accepts_nested_attributes_for call to realize that OrderLine is namespaced to Api::V1::OrderLine. Instead, rails behind the scenes is looking for just OrderLine without the namespace. How can I resolve this issue?

like image 582
JMac Avatar asked Oct 14 '15 19:10

JMac


1 Answers

I am pretty sure that the solution here is just to let Rails know the complete nested/namespaced class name.

From docs:

:class_name

Specify the class name of the association. Use it only if that name can't be inferred from the association name. So belongs_to :author will by default be linked to the Author class, but if the real class name is Person, you'll have to specify it with this option.

I usually see, that class_name option takes the string (class name) as a argument, but I prefer to use constant, not string:

module Api
  module V1
    class Order < ActiveRecord::Base
      has_many :order_lines,
        class_name: Api::V1::OrderLine
    end
  end
end

module Api
  module V1
    class OrderLine < ActiveRecord::Base
      belongs_to :order,
        class_name: Api::V1::Order
    end
  end
end
like image 196
Andrey Deineko Avatar answered Nov 07 '22 03:11

Andrey Deineko