paulelliott/fabrication-site

attributes_for doesn't work with complex objects (2.5.0)

Closed this issue · 4 comments

When I use attributes_for for a complex object, the complex object is not converted to a hash. For example:

class Order
  attr_accessor productType
  attr_accessor quoteRef
  attr_accessor allocations
  attr_accessor marketPrice
end

class Allocation
  attr_accessor account
  attr_accessor notionalAmount
end

class MarketPrice
  attr_accessor id
  attr_accessor prices
end

Fabricator :order do
  productType "Product"
  quoteRef ""
  allocations(count: 1, fabricator: :allocation)
  marketPrice(fabricator: :market_price)
end

Fabricator :allocation do
  account "10009-1"
  notionalAmount 500000.0
end

Fabricator :market_price do |f|
  f.id ""
  prices [85.7]
end
Fabricator.attributes_for(:order_do, :quoteRef=> 'olalala') = Hash (4 element(s))
  productType -> Product
  quoteRef -> olalala
  allocations = Array(1 element(s))
    [0] = {Allocation} #<Allocation:0x1140ecf2>
  marketPrice_id' ->

It is a bit annoying. Separately, I cannot use the word 'id' as an attribute, code in definition.rb:127 if value && value.respond_to?(:id) hardcodes the :id symbol and the object doesn't get parsed any further.

P.S. I am using fabricator 2.5.0, as 2.5.1 doesn't work. manager.rb [](name) tries to do a name.try(:to_sym) on a symbol, but name is already a symbol and doesn't have the try method... at least in my jruby 1.7

I have fixed it locally by implementing a to_hash method in my own code. Obviously it should be different in Fabricator taking into account the Active thingie. Is there any reason that :id is reserved for to_hash in Fabricator?

      def to_hash(object)
        return object.collect { |element| to_hash(element) } if object.is_a?(Array)
        return object if object.instance_variables.empty?

        { }.tap do |hash|
          object.instance_variables.each { |var|
            hash[var.to_s.delete('@')] = to_hash(object.instance_variable_get(var))
          }
        end
      end

Thanks for bringing this up. I have wanted to rearchitect the hashing implementation for a while but it hasn't caused me any pain so I have been putting it off. I am working on it now and hope to have something out in the next week or so.

FYI, this is the github project for http://fabricationgem.org, not the gem itself. Please open issues for the gem in the gem's project: https://github.com/paulelliott/fabrication.

What are you ultimately wanting to do with these attributes once fabrication gives them to you?

We use these attributes to send them as json-data to the server for further processing. As we use cucumber for our testing all these objects are preset with default values which you can override with test-specific data. The 'complicated' object layout represents our pojo that will be deserialised to a Java object.