I have a constant defined in my module and it is already exposed to all clients and many clients using this constant directly.
module MyModule
module Contants
FRUITS_MAP = [
{
id: 1,
name: 'Apple'
},
{
id: 2,
name: 'Coconut'
}
].freeze
end
end
Now the problem is, I want to add one more hash to FRUITS_MAP based on a condition.
if Account.enabled_feature?('Mango')
{
id: 5,
name: 'Mango'
}
Note: I don't have access to all the clients and I don't want to enforce a change in all clients but I want to add one more element to FRUITS_MAP conditionally.
For a client X with 'Mango' feature enabled, FRUITS_MAP should contain 3 elements, but for a client Y with 'Mango' feature disabled should have only 2 elements in FRUITS_MAP. How I can achieve this?
You can just return a new array by the concatenation of MyModule::Contants::FRUITS_MAP and the additional object you want in it if the condition is true:
p MyModule::Contants::FRUITS_MAP + [{ id: 5, name: 'Mango' }] if Account.enabled_feature?('Mango')
# [{:id=>1, :name=>"Apple"}, {:id=>2, :name=>"Coconut"}, {:id=>5, :name=>"Mango"}]
Related
I'm working with a class that is a subclass of JsonApiClient::Resource and can access like this (not ampersand / try sytax):
user&.professional_awards
which is like this with professional_awards being an array of Hash with Indifferent Access:
{id: 23
name: 'something',
professional_awards:[
{name: 'Best Smile'}, {name: 'Funniest'}
]
}
My question is how I access the internal professional awards in a safe way? Is there a way I could use ampersand like syntax? Or do I have to manually check? Would like to do (and options in Rails hence tagged as):
user&.professional_awards.first&['name'] # Best Smile
You're looking for Hash#dig:
hash = {
id: 23,
name: 'something',
professional_awards: [ { name: 'Best Smile' }, { name: 'Funniest' } ]
}
hash.dig(:id) # 23
hash.dig(:professional_awards) # [{:name=>"Best Smile"}, {:name=>"Funniest"}]
hash.dig(:professional_awards, 1) # {:name=>"Funniest"}
We're using Rails 5.2.2.1 as an API with Vue for the frontend.
A Post has_many :tags. A Post also accepts_nested_attributes_for :tags, allow_destroy: true.
When creating a post, you create the tags at the same time and this works well. When editing tags, however, I'm running into an issue where tags that aren't present in the update payload are not deleted from the database. Here's an example of what I'd expect:
# A Post has currently tags with ID 1, 2, and 3.
# This (pseudo) update payload is sent
{
tags_attributes: [
{
id: 1,
name: 'Tech'
},
{
id: 3,
name: 'Sports'
},
{
id: nil,
name: 'Science'
}
]
}
# The post's tag with an ID of 2 is not present in the update payload, so it should be automatically removed
# Since we're also passing up a new tag without an ID, this tag should be created
I have a solution involving _destroy: '1', but it would be preferable for tags to be automatically marked for destruction based on their presence in the update payload.
I am using a hash constant in my ROR application. I want to show the names from the hash constant to drop down.
helper.rb
PRODUCE_GROWING_METHODS = [
{id: 1, name: 'Conventional'},
{id: 2, name: 'Organic'},
]
def produce_growing_methods
PRODUCE_GROWING_METHODS
end
_produce.haml
= f.simple_fields_for :produce_details do |pd|
= pd.input :produce_growing_method, :collection => produce_growing_methods.collect { |x| [x[0], x[1]] }, :prompt => "Select Growing Method"
I tried as shown above in _produce.haml but i am getting the empty drop down. Names from the constant are not populated in drop down.
Can any one help me how to show the names from the PRODUCE_GROWING_METHODS hash constant to a drop down.
Thanks
You should map the hash by keys. In your case the keys are :id and :name:
produce_growing_methods.map { |x| [x[:id], x[:name]] }
In reality you are always better of using a generic solution rather then manual mapping.
Here is a better way of achieving the same, but it will work as well for array of thousand hashes:
ary = [
{id: 1, name: 'Conventional'},
{id: 2, name: 'Organic'},
]
ary.map(&:values)
#=> [[1, "Conventional"], [2, "Organic"]]
In Ruby on Rails 4, I'm trying to make an API for my website and instead of using an array like so:
[{id: 1, name: "John"}, {id: 2, name: "Foo"}, {id: 3, name: "Bar"}]
I want to render it like this, because it makes it much easier to search through in javascript (and for other reasons):
{"1": {id: 1, name: "John"}, "2": {id: 2, name: "Foo"}, "3": {id: 3, name: "Bar"}}
This works:
# users/index.rabl
#users.each do |user|
node(users.id.to_s) do
partial('api/v1/users/show', object: user)
end
end
But in the partial, I want another collection of elements (which belong to the user) and I can't get that working. Is there a more elegant way to do this?
To choose hash-map rather than array is definitely better option if have control on API backend codebase. From BigO notation hash lookup happens with constant O(1) time, not O(n) as for array.
Primary key lookup from the database is the most performant way to query data. Primary key is usually short and always indexed. In case of big data set use pagination.
Let's assume there is no RABL (you can always instantiate pure Ruby classes in RABL DSL code) but just an array:
array = [{id: 1, name: "John"}, {id: 2, name: "Foo"}, {id: 3, name: "Bar"}]
hash = {}
array.each{ |elem,i| hash[elem[:id].to_s] = elem }
# {"1"=>{:id=>1, :name=>"John"}, "2"=>{:id=>2, :name=>"Foo"}, "3"=>{:id=>3, :name=>"Bar"}}
To pass the Ruby hash to Javascript on client you probably want to encode it appropriately:
# hash.to_json
# {"1":{"id":1,"name":"John"},"2":{"id":2,"name":"Foo"},"3":{"id":3,"name":"Bar"}}
From Javascript you query hash by its key:
hash = {"1":{"id":1,"name":"John"},"2":{"id":2,"name":"Foo"},"3":{"id":3,"name":"Bar"}}
hash[1]
# Object { id=1, name="John"}
I'm stuck with strong_parameters and this array of hashes with a dynamic hash (hstore) inside.
The structure is the following:
{ contact_sources: [
{ id: 1, filled_fields: { randomstuff: 'randomdata', dunno: 123 } },
{ id: 2, filled_fields: { blah: 'blabla', dunno: 9043 } }
] }
So, my main attempt is the following:
params.permit(contact_sources: [{:filled_fields => []}, 'id'])
Which doesn't return filled_fields. Any suggestion on how to deal with it?
Update 1:
I have the following model:
class ContactSource < ActiveRecord::Base
# Fields: id:integer, filled_fields:hstore
end
In my action, I'm submitting multiple records at once (mass update), so I have an array of contact_source, but actually they don't belong to anything, it's just a mass update.
Looks like it's not possible to do it with "plain" strong_parameters syntax. The only option you have is to actually, after filtering, re-add those values with a loop. I know it's terrible but it's the only way right now. I submitted a bug to Rails actually.