rubygarage / api_struct

API wrapper builder with response serialization
MIT License
234 stars 21 forks source link

Validating entities #1

Closed samstarling closed 5 years ago

samstarling commented 6 years ago

Hey – I've been looking at api_struct with interest, to use in a Rails application where the models use an API for persistence, rather than a database. I'm interested in whether it's possible to rename attributes on-the-fly. For example, if I'm dealing with a messy API that, for /users/1 returns { "fNm": "Sam" }, then is there a nice way to have it so that when I do User.get(1) I have an entity with a first_name object? I'd also want to have a User.save method that I could pass User entity to, and have first_name map back to fNm when POSTing to the API. I hope that makes sense...

I think it's outside the scope of api_struct, which I'm enjoying using, but I wondered if you knew of any other gems that could do this. I know Hashie has some support for this, but it only goes in one direction.

Thanks! It's nice the the library is so small and focussed, because I can use other things for validation etc.

kirillshevch commented 6 years ago

Hi @samstarling

We solve the problem with strange keys using alias:

class User < ApiStruct::Entity
  client_service UserClient

  attr_entity :fNm

  alias first_name fNm
end

Out of the box, we do not offer something like save. But you can define it into entity/client. ApiStruct::Client provide method patch (for e.g. sample from tests)

class User < ApiStruct::Entity
  client_service UserClient

  attr_entity :id, :fNm

  alias first_name fNm

  def save
    params = {}.tap do |hash| 
      self.keys.each { |key| hash[key] = self[key] if key != 'id' } 
    end # add all attributes to params except id

    UserClient.new.update(id, params)
  end
end

class UserClient < ApiStruct::Client
  def update(id, params)
    patch(id, json: params)
  end
end

I hope it will be useful 🙂

samstarling commented 6 years ago

@kirillshevch Great, thanks for letting me know! I assume the alias only works in one direction, and that's when fetching data?

kirillshevch commented 6 years ago

Yep, only in one direction