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

Elements with specific type #351

Open
anoam opened this issue Dec 11, 2015 · 7 comments
Open

Elements with specific type #351

anoam opened this issue Dec 11, 2015 · 7 comments

Comments

@anoam
Copy link

anoam commented Dec 11, 2015

Hi!
It doesn't seems like bug or something. But it's look pretty weird for me.
Here is my code:

class Foo
  include Virtus.model(nulify_blank: true)
  attribute :int_array, Array[Integer]
end

foo = Foo.new(int_array: ["", "1", 2, "1bar", "baz"])
foo.int_array #=> ["", 1, 2, "1bar", "baz"]

Is there ways to drop attributes that wasn't converted to integer?

@hl
Copy link

hl commented Dec 29, 2015

This is correct behaviour, how would you coerce "baz" to a Integer?

You can filter it yourself

foo.int_array.select { |k,v| v.is_a? Integer }

@envygeeks
Copy link
Contributor

@zenry no it's not and it never will be. If a user asks for an integer array and a non-integer is given it should throw at minimum or reject at the extreme... that is correct behavior.

@hl
Copy link

hl commented Dec 29, 2015

Well I have strict mode on so in my case it will fail loudly. That said I would not like Virtus or any library for that matter to just discard elements in my array. Coerce in non strict mode means to me that it will try to coerce it into the proper type and leave the rest as is.

What you guys want sounds more like a filter.

@envygeeks
Copy link
Contributor

I don't think it should coerce that's for sure, I think it should throw though.

@hl
Copy link

hl commented Dec 29, 2015

Agreed, but I also like that fact that you can turn that option on and off (strict mode)

@anoam
Copy link
Author

anoam commented Feb 12, 2016

Hi!
Sorry for my late reply.
First of all, I want to say that coercing array elements ignores nulify_blank: true.
In my example even "" was casted as "", not nil.

Second, default coersions are unexpectable.
When result of coercing "baz" to Integer is "baz" also looks little bit weird.
I expected to see 0 or `nil.
Using strict can be useful. But does not raising-catching exceptions means bad performance?
Ofcourse, I can resolve it with custom coercion.

But coercing arrays is problem for me.
Is there any ways to customize it?
I want something like this:

class MyInteger < Virtus::Attribute
  primitive Integer

  def coerce(input)
    res = super
    res.is_a?(Integer) ? res : nil
  end
end

class MyArray < Virtus::Attribute::Array
  def coerce
    super.uniq.compact
  end
end

class Foo
  include Virtus.model(nulify_blank: true)

  attribute :int_array, MyArray[MyInteger]
end

So, behaviour I look for, could be like this:

Foo.new(int_array: ["", "1", 2, "1bar", "baz"]).int_array #=> [1, 2]

In sources I found Collection class. It looks like what i need. But it's documentation is poor. I can't understand how to use it.

Also I could override getter like this.

class Foo::ArrayCoercer
  def initialize(array)
    @array = array
  end

  def to_a
    @array.uniq.compact
  end
end

class Foo
  include Virtus.model(nulify_blank: true)

  attribute :int_array, Array[Integer]

  def int_array
    ArrayCoercer.new(super)
  end
end

@phstc
Copy link

phstc commented Oct 5, 2016

I'm facing a similar issue. I want a custom Array attribute, that ignores nil entries:

class CompactedArray < Virtus::Attribute::Array
  def coerce(value)
    super&.compact
  end
end

class Foo
  include Virtus.mode

  attribute :bars, CompactedArray[Bar]
end

But coerce never gets called. It does work if I replace Virtus::Attribute::Array with Virtus::Attribute, but then it will complain about other methods that need to be implemented in my CompactedArray. Any ideas on how to implement it?

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

4 participants