Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActiveRecord::AssociationTypeMismatch got Hash with nested resources #125

Closed
sbwoodside opened this issue Jan 16, 2016 · 6 comments
Closed

Comments

@sbwoodside
Copy link

I am trying to create new objects with a collection of nested resources. When I POST my json, I get:

ActiveRecord::AssociationTypeMismatch: FormLabel(#70306552439440) expected, got Hash(#70306480154920)

Here's my code:

# form.rb
class Form < ActiveRecord::Base
  has_many :form_labels
  validates_presence_of :name
end

# form_label.rb
class FormLabel < ActiveRecord::Base
  belongs_to :form
  validates_presence_of :form
  validates_presence_of :text
end

# form_representer.rb
module FormRepresenter
  include Roar::JSON
  property :id
  property :name
  collection :form_labels
end

# form_label_representer.rb
module FormLabelRepresenter
  include Roar::JSON
  property :text  
end

# form_controller.rb
class FormsController < ApplicationController
  include Roar::Rails::ControllerAdditions
  def create
    form = Form.new
    consume!(form)
    respond_with(form)
  end

When I debug, these are the params:

0> params
=> {"name"=>"Address", "form_labels"=>[{"text"=>"foo"}], "format"=>"json", "controller"=>"forms", "action"=>"create", "form"=>{"name"=>"Address"}}

and the error is:

ActiveRecord::AssociationTypeMismatch: FormLabel(#70237358584300) expected, got Hash(#70237286721880)
@apotonick
Copy link
Member

Your representers are incorrect. Representable doesn't know that your collection :form_labels items are going to deserialize into FormLabel objects, you need to use the :class option: http://trailblazer.to/gems/representable/3.0/api.html#nested-parsing

@apotonick
Copy link
Member

BTW - keep up posting relevant code snippets in support requests! 👍 Many people only do that after being asked for it, this speeds up debugging greatly! 😜

@sbwoodside
Copy link
Author

You're welcome :-)

Thanks for the pointer, my test passes now. Now I can set up POSTs for my whole API using your representers, which should greatly simplify and reduce the code. (I'm testing my API with rspec_api_documentation.)

I have changed:

  collection :form_labels

to

 collection :form_labels, decorator: FormLabelRepresenter, class: FormLabel

However, I expected that the original to work because in Rails typically convention over configuration, I assumed it would automatically check for a a Representer and a class with those names. Can I request that as a feature?

Also, may I suggest that you add a small example to this roar-rails documentation, I read through all the docs for roar, roar-rails and Representable, and it's not always obvious exactly how they play together. For example, why in Rails am I not subclassing Representable::Decorator?

@apotonick
Copy link
Member

First of all, I do not support roar-rails anymore because I think it is wrong, as it only fixes Rails partly. Trailblazer is what you should check out, you still have representers, but they are used from within an operation, in combination with a form object.

Since I strongly believe in this architectural pattern, I don't want to encourage more people to go the Rails Way, which is fundamentally wrong in almost everything it does, I'm not sure if I want to invest any more time in this gem. If you write up a nice introduction, I'm more happy to link to it here, or merge your README additions. Also, roar-rails is only a bridging to Rails, the actual gem, Roar is the clean implementation we use in Trailblazer, too, and that's where people should be reading.

Conventions in Rails might be nice for the start but they get in your way pretty fast, which is why I decided to keep my gems very explicit. Thanks for offering the convention patch, but this will only end up in trouble - and will be a breaking API change, although I can see how that would help you.

@sbwoodside
Copy link
Author

I had a look at your Trailblazer site about a week ago. It's very interesting. I'm on a tight timeline for the API at present, so I'm hesitant to make a major architectural change right now. I think I might have misunderstood what I read before though, because I thought that Trailblazer was a rack app that replaced rails. Now I looked at https://github.com/apotonick/trailblazer and I see that it's actually on top of rails.

I picked out roar-rails because it seems like it allows me to get a lot of proper REST API / JSON handling with a lot less code. I definitely have read the Roar docs carefully and I understand that roar-rails is just sitting on top of that.

Given that I'm presently using ActiveRecord, rails controllers in a pretty minimal way, devise for authentication, and rspec_api_documentation, how big a change would it be to switch from roar-rails to trailblazer?

@apotonick
Copy link
Member

Haha, I like where this conversation is going! 🍻

Minimal controllers sound good. However, where does all your business logic sit? Deserialization is done by Roar, ok, but validation, nested validations, post-processing logic (aka callbacks)? Is that in your models or service objects?

I'd recommend that you implement the next API endpoint (e.g. POST /comments/) with TRB (in the existing app) and play with that for 1 day just to get a feeling. With TRB, you don't have to rewrite everything, you can do baby-steps, which I find pretty cool.

You will realise that you already know many things since you must be a master of Roar as I write this. I'm happy to help you a bit, and I am not angry with you if you decide that you won't switch everything to TRB tomorrow, because I wouldn't do that either if time's short.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants