Call property programmatically in Ruby [duplicate] - ruby

This question already has answers here:
How to call methods dynamically based on their name? [duplicate]
(5 answers)
Closed 5 years ago.
I have a Ruby project where I programmatically get the names of keys in a hash I need to access. I can access the fields I need in the following way:
current_content = entry.fields[property_name.to_sym]
However, it seems that some content can only be accessed with a property syntax:
m.title_with_locales = {'en-US' => 'US Title', 'nl' => 'NL Title'}
Since I don't know "title" ahead of time, how can I make a call programmatically? Ex:
m.${property_name}_with_locales = {'en-US' => 'US Title', 'nl' => 'NL Title'}

You can use #send to programmatically access properties:
m.send("#{property_name}_with_locales")
# => { 'en-US' => 'US Title', ... }
If you need to access a setter and pass in values, you can do:
m.send("#{property_name}_with_locales=", { 'whatever' => 'value' })

beside send as #gwcodes had written, there are also, eval and call.
2.3.1 :010 > a
=> [1, 2, 3]
2.3.1 :011 > a.send("length")
=> 3
2.3.1 :012 > a.method("length").call
=> 3
2.3.1 :013 > eval "a.length"
=> 3
as shown on this blog post call is a bit faster than send.

Related

Elegantly return value(s) matching criteria from an array of nested hashes - in one line

I have been searching for a solution to this issue for a couple of days now, and I'm hoping someone can help out. Given this data structure:
'foo' => {
'bar' => [
{
'baz' => {'faz' => '1.2.3'},
'name' => 'name1'
},
{
'baz' => {'faz' => '4.5.6'},
'name' => 'name2'
},
{
'baz' => {'faz' => '7.8.9'},
'name' => 'name3'
}
]
}
I need to find the value of 'faz' that begins with a '4.', without using each. I have to use the '4.' value as a key for a hash I will create while looping over 'bar' (which obviously I can't do if I don't yet know the value of '4.'), and I don't want to loop twice.
Ideally, there would be an elegant one-line solution to return the value '4.5.6' to me.
I found this article, but it doesn't address the full complexity of this data structure, and the only answer given for it is too verbose; the looping-twice solution is more readable. I'm using Ruby 2.3 on Rails 4 and don't have the ability to upgrade. Are there any Ruby gurus out there who can guide me?
You can use select to filter results.
data = {'foo' => {'bar' => [{'baz' => {'faz' => '1.2.3'}, 'name' => 'name1'}, {'baz' => {'faz' => '4.5.6'}, 'name' => 'name2'}, {'baz' => {'faz' => '7.8.9'}, 'name' => 'name3'}]}}
data.dig('foo', 'bar').select { |obj| obj.dig('baz', 'faz').slice(0) == '4' }
#=> [{"baz"=>{"faz"=>"4.5.6"}, "name"=>"name2"}]
# or if you prefer the square bracket style
data['foo']['bar'].select { |obj| obj['baz']['faz'][0] == '4' }
The answer assumes that every element inside the bar array has the nested attributes baz -> faz.
If you only expect one result you can use find instead.

colon placement in Ruby 2.2+ [duplicate]

This question already has answers here:
Is there any difference between the `:key => "value"` and `key: "value"` hash notations?
(5 answers)
Closed 7 years ago.
I see colons used two different ways in Ruby
:controller => 'pages'
and then
action: => 'home'
I found an explanation here: http://goo.gl/ZKxKVK
it seems that the position doesn't matter, could someone clarify this?
Mostly it doesn't matter. Since Ruby 1.9 we can use more short form:
h = { a: 1, b: 2}
But there are some situations where you have to use the longest form, e.g.:
h = {1 => 'a', 2 => 'b'}
h = {"One Two" => 1}
action: => 'home' is not valid syntax.
It should be action: 'home' or :action => 'home'.
These are equivalent. They generate:
{:action=>'home'}

Is there a way to tell Psych in ruby to using inline mode?

environment: ruby1.9.3 , psych(any version)
ex:
o = { 'hash' => { 'name' => 'Steve', 'foo' => 'bar' } }
=> {"hash"=>{"name"=>"Steve", "foo"=>"bar"}}
#is there a inline option?
puts Psych.dump(o,{:inline =>true})
real result:
---
hash:
name: Steve
foo: bar
expect output:
---
hash: { name: Steve, foo: bar }
Psych supports this, although it isn't at all straightforward.
I've started researching this in my own question on how to dump strings using literal style.
I ended up devising a complete solution for setting various styles for specific objects, including inlining hashes and arrays.
With my script, a solution to your problem would be:
o = { 'hash' => StyledYAML.inline('name' => 'Steve', 'foo' => 'bar') }
StyledYAML.dump o, $stdout
The representable gem provides this in a convenient OOP style.
Considering you have a model User:
user.name => "Andrew"
user.age => "over 18"
You'd now define a representer module to render/parse User instances.
require 'representable/yaml'
module UserRepresenter
include Representable::YAML
collection :hash, :style => :flow
def hash
[name, age]
end
end
After defining the YAML document you simply extend the user instance and render it.
user.extend(UserRepresenter).to_yaml
#=> ---
hash: [Andrew, over 18]
Hope that helps, Andrew!

Finding out variable class and difference between Hash and Array

Is it possible to clearly identify a class of variable?
something like:
#users.who_r_u? #=>Class (some information)
#packs.who_r_u? #=> Array (some information)
etc.
Can someone provide clear short explanation of difference between Class, Hash, Array, Associated Array, etc. ?
You can use:
#users.class
Test it in irb:
1.9.3p0 :001 > 1.class
=> Fixnum
1.9.3p0 :002 > "1".class
=> String
1.9.3p0 :003 > [1].class
=> Array
1.9.3p0 :004 > {:a => 1}.class
=> Hash
1.9.3p0 :005 > (1..10).class
=> Range
Or:
1.9.3p0 :010 > class User
1.9.3p0 :011?> end
=> nil
1.9.3p0 :012 > #user = User.new
=> #<User:0x0000010111bfc8>
1.9.3p0 :013 > #user.class
=> User
These were only quick irb examples, hope it's enough to see the use of .class in ruby.
You could also use kind_of? to test wheter its receiver is a class, an array or anything else.
#users.kind_of?(Array) # => true
You can find these methods in Ruby document http://ruby-doc.org/core-1.9.3/Object.html
#user.class => User
#user.is_a?(User) => true
#user.kind_of?(User) => true
found helpful: <%= debug #users %>
A difference between Class and Hash? They are too different to even provide normal answer. Hash is basically an array with unique keys, where each key has its associated value. That's why it's also called associative array.
Here is some explanation:
array = [1,2,3,4]
array[0] # => 1
array[-1] # => 4
array[0..2] # => [1,2,3]
array.size # => 4
Check out more Array methods here: http://ruby-doc.org/core-1.9.3/Array.html
hash = {:foo => 1, :bar => 34, :baz => 22}
hash[:foo] # => 1
hash[:bar] # => 34
hash.keys # => [:baz,:foo,:bar]
hash.values # => [34,22,1]
hash.merge :foo => 3921
hash # => {:bar => 34,:foo => 3921,:baz => 22 }
Hash never keeps order of the elments you added to it, it just preserves uniqueness of keys, so you can easily retreive values.
However, if you do this:
hash.merge "foo" => 12
you will get
hash # => {:bar => 34, baz => 22, "foo" => 12, :foo => 2}
It created new key-value pair since :foo.eql? "foo" returns false.
For more Hash methods check out this: http://www.ruby-doc.org/core-1.9.3/Hash.html
Class object is a bit too complex to explain in short, but if you want to learn more about it, reffer to some online tutorials.
And remember, API is your friend.

Ruby: Create hash with default keys + values of an array

I believe this has been asked/answered before in a slightly different context, and I've seen answers to some examples somewhat similar to this - but nothing seems to exactly fit.
I have an array of email addresses:
#emails = ["test#test.com", "test2#test2.com"]
I want to create a hash out of this array, but it must look like this:
input_data = {:id => "#{id}", :session => "#{session}",
:newPropValues => [{:key => "OWNER_EMAILS", :value => "test#test.com"} ,
{:key => "OWNER_EMAILS", :value => "test2#test2.com"}]
I think the Array of Hash inside of the hash is throwing me off. But I've played around with inject, update, merge, collect, map and have had no luck generating this type of dynamic hash that needs to be created based on how many entries in the #emails Array.
Does anyone have any suggestions on how to pull this off?
So basically your question is like this:
having this array:
emails = ["test#test.com", "test2#test2.com", ....]
You want an array of hashes like this:
output = [{:key => "OWNER_EMAILS", :value => "test#test.com"},{:key => "OWNER_EMAILS", :value => "test2#test2.com"}, ...]
One solution would be:
emails.inject([]){|result,email| result << {:key => "OWNER_EMAILS", :value => email} }
Update: of course we can do it this way:
emails.map {|email| {:key => "OWNER_EMAILS", :value => email} }

Resources