Git Product home page Git Product logo

Comments (11)

zauner avatar zauner commented on May 18, 2024 1

Thanks, I came pretty far with the after_initialize workaround, by making the fields Union(PG::Numeric,Float64), and then .to_fing in the after_initialize hook.

But i can't get completely rid of the PG::Numeric type. I guess I will just work with the numerics for now, and hope for a solution in 0.6.0 :)

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

ATM to use numeric field you have to specify it PG::Numeric. Possible workaround may be specifying after_initialize callback with converting numeric field to float. But anyway this sounds reasonable - will try to add some way how to handle such a case in 0.6.0.

from jennifer.cr.

zauner avatar zauner commented on May 18, 2024

Ok, I had to pursue this after all. Here's my workaround following your suggestion:

  • Use Union(PG::Numeric|Float64) as type in the column mapping to satisfy the res.read(...) call
  • Convert the field to Float64 after initalize
  • Add (override? not sure ...) the getter with a variant that returns Float64
class Product < Jennifer::Model::Base

  mapping({
    # [...]
    price: Union(PG::Numeric, Float64),
    # [...]
  })

  after_initialize :n2f
  def n2f
    @price = @price.to_f64.as(Float64)
  end

  def price : Float64
    @price.as(Float64)
  end
  
end

I packed it into a macro:

module ConvertNumerics

  macro convert_numerics(props)
    after_initialize :n2f
    def n2f
      {% for prop in props %}
        @{{prop}} = @{{prop}}.to_f64.as(Float64)
      {% end %}
    end

    {% for prop in props %}
      def {{prop.id}} : Float64
        @{{prop.id}}.as(Float64)
      end
    {% end %}
  end

end

to be able to use it like this in my models:

class Product < Jennifer::Model::Base
  include ConvertNumerics

  mapping({
    # [...]
    price: Union(PG::Numeric, Float64),
    # [...]
  })

  convert_numerics [price]
  
end

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

But this way you applied only a one way binding - this will not reflect data changes during saving an object. A little bit later will provide similar but slightly different possible workaround

from jennifer.cr.

zauner avatar zauner commented on May 18, 2024

That's right. Couldn't find a painless way to create a PG::Numeric object, and so far my app is still read-only :)

But I guess the better solution would be anyway, to get rid of PG::Numeric immediatly after reading from the database, and don't let it come to the point that getters/setters have to deal with it.

from jennifer.cr.

zauner avatar zauner commented on May 18, 2024

Also, Postgres' Numerics should rather be mapped to BigDecimal than to Float64, right?

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

Now on v0.6.0 you can do

class Product < Jennifer::Model::Base
  include ConvertNumerics

  mapping({
    # [...]
    price: { type: Float64, numeric_converter: :to_f64 },
    # [...]
  })
end

from jennifer.cr.

zauner avatar zauner commented on May 18, 2024

Cool, works great when reading from the DB!

However, when building an object from Hash like this

p = Product.build(
  # [...]
  price: 1000.0_f64
)

I am getting

cast from Float64 to PG::Numeric failed

I tracked it down to this location:

values[{{column}}]{% if value[:numeric_converter] %}.as(PG::Numeric).{{value[:numeric_converter].id}}{% end %}

and when removing the casts and conversions in that line like it was before, everything's fine:

%var{key.id} = values[{{column}}]

I think it makes sense. The value from the incoming Hash should be Float64 (or whatever you have in the mapping) anyway, right?

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

Hi. Sorry for so long response. Yes, the root cause is in this line. Will add workaround here but AFAIK we can't allow passing only Float64 in such case - a parsed db result set may be passed to the constructor.

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

@zauner Finally, I got a free minute. I believe allow_non_numeric_hash_ar_for_model_with_numeric_constructor branch should fit your need. Please clarify if there is no more issue with this case and I will merge it.

from jennifer.cr.

imdrasil avatar imdrasil commented on May 18, 2024

@zauner please clarify is this issue is resolved

from jennifer.cr.

Related Issues (20)

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.