pcriv / statics

Base class and modules for YAML backed static models.
MIT License
43 stars 3 forks source link

Support for optional fields (allow_nil) #4

Closed inem closed 6 years ago

inem commented 6 years ago

Use case:

rubyfuza:
  title: Ruby Fuza 2019
  start_date: 2019-02-07
  end_date: 2019-02-08
  location: Cape Town, Africa
  twitter: rubyfuza
  website: https://www.rubyfuza.org/
  topic: ruby

craftconf:
  title: Craft 2019
  start_date: 2019-05-09
  end_date: 2019-05-10
  location: Budapest, Hungary
  twitter: CraftConf
  website: https://craft-conf.com/
  cfp: https://www.papercall.io/craft-conf-2019
  cfp_until: 2018-10-15
  topic: broad

There's no info about CFP for RubyFuza, but now I have to provide something, and this something should be of correct type.

For the code above I get ([Conference.new] :cfp is missing in Hash input)

inem commented 6 years ago

Aha, I see. This actually helps:

  attribute :cfp,        Types::Strict::String.optional
  attribute :cfp_until,  Types::Strict::Date.optional

Although, it fails when I try to sort it:

irb(main):042:0> Conference.all.sort{|a,b | a.cfp_until <=> b.cfp_until }
Traceback (most recent call last):
        2: from (irb):42
        1: from (irb):42:in `sort'
ArgumentError (comparison of Conference with Conference failed)
inem commented 6 years ago

Alright, solved my problem with Conference.where_not(cfp: nil).sort{|a,b | a.cfp_until <=> b.cfp_until }

pcriv commented 6 years ago

@inem Glad to see you found a solution :) shall i close this issue?

inem commented 6 years ago

Oh, I forgot to mention that I had to add two blank fields in order to get the solution above working:

rubyfuza:
  title: Ruby Fuza 2019
  start_date: 2019-02-07
  end_date: 2019-02-08
  location: Cape Town, Africa
  twitter: rubyfuza
  website: https://www.rubyfuza.org/
  cfp:
  cfp_until:
  topic: ruby

It would be great, if I could simply skip these empty definitions in YAML file, but now it is not possible.

So, up to you on closing the issue, depending on how do you want it to work.

pcriv commented 6 years ago

You can if you do:

Types::Params::Date.meta(omittable: true).optional
Types::Strict::String.meta(omittable: true).optional

For more info about the Types API check https://dry-rb.org/gems/dry-types

inem commented 6 years ago

Oh, cool. Didn't know about this feature of dry-types! Although it doesn't seem to work:

irb(main):001:0> Conference.all
Traceback (most recent call last):
        1: from (irb):1
Dry::Struct::Error ([Conference.new] :cfp is missing in Hash input)

the model:

class Conference < Statics::Model
  filename "conferences"

  attribute :title,      Types::Strict::String
  attribute :start_date, Types::Strict::Date
  attribute :end_date,   Types::Strict::Date
  attribute :location,   Types::Strict::String
  attribute :twitter,    Types::Strict::String.optional
  attribute :website,    Types::Strict::String
  attribute :topic,      Types::Strict::String
  attribute :cfp,        Types::Strict::String.meta(omittable: true).optional
  attribute :cfp_until,  Types::Params::Date.meta(omittable: true).optional
end

the data:

---
rubyfuza:
  title: Ruby Fuza 2019
  start_date: 2019-02-07
  end_date: 2019-02-08
  location: Cape Town, Africa
  twitter: rubyfuza
  website: https://www.rubyfuza.org/
  topic: ruby

craftconf:
  title: Craft 2019
  start_date: 2019-05-09
  end_date: 2019-05-10
  location: Budapest, Hungary
  twitter: CraftConf
  website: https://craft-conf.com/
  cfp: https://www.papercall.io/craft-conf-2019
  cfp_until: 2018-10-15
  topic: broad
pcriv commented 6 years ago

🤔 Alright i'll try to take a deeper look ASAP

pcriv commented 6 years ago

@inem Types::String.meta(omittable: true) should do the work.

I had it wrong that you needed to use both at the same time:

# works
Types::String.optional.meta(omittable: true)

# doesn't work
Types::String.meta(omittable: true).optional

But i think the last method takes precedence, so we should just use meta(omittable: true) that covers what optional does.

EDIT:

Also, i think you need the optional if you use the Strict version.

inem commented 6 years ago

Hurray! Thanks for helping me with this case!

I think it might worth to elaborate a bit more on how to handle different typical cases in Yaml files with dry-types. If more people who are not experienced in dry-types (like me), will come, they gonna have some problems :)

pcriv commented 6 years ago

Good suggestion @inem I'll try to add something to the README.