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

Hash with dynamic keys but consistently typed values? #459

Open
YGKtech opened this issue May 3, 2019 · 4 comments
Open

Hash with dynamic keys but consistently typed values? #459

YGKtech opened this issue May 3, 2019 · 4 comments
Assignees
Labels

Comments

@YGKtech
Copy link

YGKtech commented May 3, 2019

I often deal with data structures like this:

    records_map = {
        "11" => {
            id: 1,
            name: 'something'
        },
        "2" => {
            id: 2,
            name: 'something else'
        },
        "7" => {
            id: 7,
            name: 'FIRST!'
        }
    }

where every key-value pair within the hash has a strict type definition, but the has may have any number of those pairs.

Based on my reading of the docs, and testing with the code, I don't think there's a way to express this structure. You can use it by allowing a hash with arbitrary keys, but that loses type-safety one that object.

For now I've worked around this by putting all the key-value pairs into an array before passing them into the interaction, then re-building the hash inside the interaction. It works, but it requires some extra code, and has some performance implications when dealing with very large records.

I'd like to know if there actually is a way to support this pattern that I've just missed, or if there's any plans to add support for it in a future version?

@AaronLasseigne
Copy link
Owner

Right now I believe you are correct. We have no way to handle that structure while using types. No one has requested it before so it's certainly not something we're planning to add. Let me think about what it might take to add something like that.

@YGKtech
Copy link
Author

YGKtech commented May 6, 2019

@AaronLasseigne : Thanks, I'll continue leaning on the array workaround for my use case then.

For implementation, I'd imagine it could reuse a lot of the validation code you already have for arrays, but I'm not sure how to reconcile this pattern with the syntax you've used for other structures.

To give a little more context, structures like this often come up in my work when dealing with NoSQL datastores, especially ones that rely heavily on JSON, like Firebase, where a records unique ID isn't part of the record itself, just a key that points to it. I think most Ruby/Rails projects tend towards use cases where these sort of datastores aren't appropriate/necessary, so it makes sense that this wouldn't come up as quickly as other structures.

I'm sure there will be a few other people out there who eventually want something like this, since Interactions are actually a great fit for enforcing consistency in data structures when working with a schemaless NoSQL store, but obviously it's still a bit of a niche audience.

Thanks.

@usamaSaddiq
Copy link

usamaSaddiq commented Jul 4, 2022

+1 I'm facing a similar issue where we're trying to bulk update metrics from various years and the year value acts as a composite key along with another field to uniquely identify a record. Example structure

 "2016": {
    metric_name: value
#    ..... and so on for other hashes too, the keys in the hash are consistent.
  },
  "2017": {
....
  },
  "2018": {
.....
  },
  "2019": {
....
  },
......

I've also got a workaround where instead of passing the values as an array, I'm calling the interaction 4 times in the above instance because each call to the interaction updates 4 seperate records and chucking them in a single SQL is hard

    update_outcomes = years.reduce([]) do |outcomes, year|
      outcomes << UpdateMetrics.run({
        :year => year.to_i,
        :metrics => metrics_by_year[year]
         ........ other params with id
      })
    end

........and then

if update_outcomes.all?(&:valid?)
      head :no_content
else
      render :json => { :message => "Bad Request" }.to_json, :status => :bad_request
end

Might be a good idea to let hash keys be identifiable via a regex/be dynamic with a type? Sometimes we don't know how many years worth of metrics we're going to get so we could have structures like this

hash :metrics, default: {} do
  1..years do |year|
         hash (year <-dynamic key with type)) do
           with_options default: nil do
             ..... do something with keys
           end
         end
   end
end

Hope that helps.

@AaronLasseigne
Copy link
Owner

I'm considering solutions for this. See #535.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants