Giter Club home page Giter Club logo

model_attribute's People

Contributors

dwaller avatar enrico-scalavino avatar fastdivision avatar kjrocker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

model_attribute's Issues

Rename attributes when transforming to/from JSON

Hi.

Just wanted to pitch an idea and see what you think: I'm writing an integration gem for a public API. Like many JSON APIs it uses CamelCase for the key names that do not map cleanly to ruby attribute names. For example:

PriceInclVAT should map to price_incl_vat but the gem doesn't do any conversions, leaving you with two choices: roll your own or live with the weird attribute names.

I'd like to add the ability to convert key names when transforming to/from JSON. One way would be to just do a straight map, given at attribute declaration time:

require 'model_attribute'
class User
  extend ModelAttribute
  attribute :id,             :integer, key: 'UserID'
  attribute :paid,           :boolean, key: 'Paid' 
  attribute :name,           :string,  key: 'UserName'
  attribute :created_at,     :time,    key: 'RegistrationTime'
  attribute :vat_schedule,   :json,    key: 'VATSchedule'

  def initialize(attributes = {})
    set_attributes(attributes)
  end
end

or by assigning a conversion method

require 'model_attribute'
class User
  extend ModelAttribute
  attribute :id,             :integer
  attribute :paid,           :boolean
  attribute :name,           :string
  attribute :created_at,     :time
  attribute :vat_schedule,   :json

  def convert( key, export = false )
    map = {
      id: 'UserID',
      paid: 'Paid',
      name: 'UserName',
      created_at: 'RegistrationTime',
      vat_schedule: 'VATSchedule',
    }
    map.reverse! if export
    map[ key ]
  end

  def initialize(attributes = {})
    set_attributes(attributes)
  end
end

Idealy you could do both, use the key directly if it exists and call the method if it doesn't.

require 'model_attribute'
class User
  extend ModelAttribute
  attribute :id,             :integer, key: 'UserID'
  attribute :paid,           :boolean
  attribute :name,           :string,  key: 'UserName'
  attribute :created_at,     :time,    key: 'RegistrationTime'
  attribute :vat_schedule,   :json,    key: 'VATSchedule'

  def convert( key, export = false)
    return key.to_s.capitalize unless export
    'UserID'.gsub(/(.+[a-z])([A-Z])/, '\1_\2' ).downcase.to_sym
  end

  def initialize(attributes = {})
    set_attributes(attributes)
  end
end

Right now I use Virtus with a hand rolled version of the combined approach. I have a map and a generic method. If the key is in the map it's used else the method is run.

Would this be interesting for you? If so I can open a PR when I have something that we can discuss.

JSON type doesn't accept hashes with symbol keys

class Foo
  attribute :metadata, :json
end

instance = Foo.new

If you give a Hash with string keys, all is well:

instance.metadata = {"master" => "chief"}
#=> {"master" => "chief"}

However, if you provide a Hash with symbol keys (which might have happened depending on how your JSON was generated or if it came from elsewhere e.g. Yaml):

instance.metadata = {:master => "chief"}
#=> ArgumentError: JSON only supports nil, numeric, string, boolean and arrays and hashes of those.

I think this is a bug because it's non-obvious behaviour, especially in Ruby where hashes can have ambiguous key semantics. There's probably three solutions:

  1. Sanitise your inputs! (Nested stringify all your keys before pushing into the model)
  2. Stringify keys with the writer (metadata=) method
  3. Accept symbol keys, potentially the primitive type "symbol" (even knowing that JSON doesn't recognise that type).

Inheritance support

Hello I'm facing the issue with inheritance, attributes are not being copied.

Ruby 2.3.1
model_attribute (3.1.1)

require 'model_attribute'
class Person
  extend ModelAttribute
  attribute :name,       :string
  attribute :last_name,       :string

  def initialize(attributes = {})
    set_attributes(attributes)
  end
end


class User < Person

  def initialize(attributes = {})
    super(attributes)
    self.name = "This is an error"
  end
end


User.attributes # nil
User.new({})

# /Users/soto/.rvm/gems/ruby-2.3.1/gems/model_attribute-3.1.1/lib/model_attribute.rb:87:in `read_attribute': undefined method `include?' for nil:NilClass (NoMethodError)
# 	from /Users/soto/.rvm/gems/ruby-2.3.1/gems/model_attribute-3.1.1/lib/model_attribute.rb:66:in `write_attribute'
# 	from /Users/soto/.rvm/gems/ruby-2.3.1/gems/model_attribute-3.1.1/lib/model_attribute.rb:27:in `name='
# 	from script.rb:17:in `initialize'
# 	from script.rb:22:in `new'
# 	from script.rb:22:in `<main>'

Rails form model support

I suggest to make it clear in the README that if you want to use this Models in your Rails form you will need to add:

include ActiveModel::Conversion
extend  ActiveModel::Naming

def persisted?
  false
end

To your model

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.