How I can create a hash like this in a cycle ?
User.items.each do |m|
......
Result:
test = [{:name => 'Unit 1', :price => "10.00"},
{:name => 'Unit 2', :price => "12.00"},
{:name => 'Unit 3', :price => "14.00"}]]
You can use map to return hashes that you build.
Assuming your Item resource responds to name and price, it would look like
test = User.items.map do |m|
{
name: m.name,
price: m.price
}
end
You also can do like this:
Item.connection.select_all("select name, price from items where user_id = xxxxx;")
you will get an array containing hash, like this:
[{"name"=>"xxx", "price"=> xxx},{}......]
Related
i'm new to ruby and i want to instersect two arrays
validAccountTypes = [
'Asset' => 'Asset',
'Liability' => 'Liability',
'Equity' => 'Equity',
'Income' => 'Income',
'CostOfSales' => 'Cost of Sales',
'Expense' => 'Expenses',
'OtherIncome' => 'Other Income',
'OtherExpense' => 'Other Expenses',
]
types = [
'Asset',
'Other Income',
'Other Expenses',
]
I want a result of valid Accounts with keys base on array types. The output would be
[{"Asset"=>"Asset", "OtherIncome"=>"Other Income", "OtherExpense" => "Other Expenses"}]
Is it possible without a loop?
Here's a rewrite of your variables with a few changes:
Underscore variable names
valid_account_types is now a hash instead of an array containing a hash.
Some typos corrected so that the members of types match keys of valid_account_types.
valid_account_types = {
'Asset' => 'Asset',
'Liability' => 'Liability',
'Equity' => 'Equity',
'Income' => 'Income',
'CostOfSales' => 'Cost of Sales',
'Expense' => 'Expenses',
'OtherIncome' => 'Other Income',
'OtherExpenses' => 'Other Expenses',
}
types = [
'Asset',
'OtherIncome',
'OtherExpenses',
]
Given that setup, if you are using Rails, you can get the result you want using Hash#slice, like this:
> valid_account_types.slice(*types)
=> {"Asset"=>"Asset", "OtherIncome"=>"Other Income", "OtherExpenses"=>"Other Expenses"}
Note that Hash#slice does not exist in Ruby itself. If you want to do this in plain-old Ruby, you could check out the implementation in i18n:
class Hash
def slice(*keep_keys)
h = self.class.new
keep_keys.each { |key| h[key] = fetch(key) if has_key?(key) }
h
end
end
Your first array isn't an array, it's actually a hash (notice the surrounding braces, rather than brackets):
validAccountTypes = {
'Asset' => 'Asset',
'Liability' => 'Liability',
'Equity' => 'Equity',
'Income' => 'Income',
'CostOfSales' => 'Cost of Sales',
'Expense' => 'Expenses',
'OtherIncome' => 'Other Income',
'OtherExpense' => 'Other Expenses',
}
You can get the keys on the hash and intersect it with your array:
common_keys = validAccountTypes.keys & types
Then you can select only those keys:
# Hash#slice works in Rails:
validAccountTypes.slice(*common_keys)
# Otherwise use Hash#select:
validAccountTypes.select { |key, value| common_keys.include?(key) }
Note that in your example, your hash keys include 'OtherIncome' and 'OtherExpense', but your types array includes 'Other Income' and 'Other Expenses'. Your array values should match the keys from the hash.
I have Item model(table) with column [id,name,notes]. then I have hash lets call it stock with column [id_of_item,total_stock],
when I do query in controller I would like to join the hash into the table as additional column so I can show the total_stock of the item.
I prefer not to use map/each (looping through all the items since the items table has thousand records. I still don't know whether this possibly or not, thank you.
if your stock is
[[1, "total_stock_1"], [2, "total_stock_2"]]
you should use
stock = Hash[[[1, "total_stock_1"], [2, "total_stock_2"]]]
to translate your hash to this style
stock = {1 => "total_stock_1", 2 => "total_stock_2"}
stock = {1 => "total_stock_1", 2 => "total_stock_2"}
#items = Item.all.map{|item| item.attributes.merge({total_stock: stock[item.id]})}
# the output will be a json not a ActiveRecordRelation
[
{:id => 1, :name => 'item1', :notes => xxx, :total_stock => "total_stock_1"},
{:id => 2, :name => 'item2', :notes => yyy, :total_stock => "total_stock_2"}
]
You can do this in controller:
#items = Item.all
render json: #items.map{|item| {'item': item.as_json.merge stock.select{|item| item['id_of_item'] == item.id}['total_stock']} }}
I am loading data from database and saving it to a constant like this:
profession = Hash.new
Profession.all.each do |p|
profession[p.name] = p.unique_profession
profession[p.name]['descr'] = p.description # problem
profession[p.name]['created_at'] = p.created_at # problem
end
On the line profession[p.name]['descr'] occurs this error:
undefined method `[]=' for 1:Fixnum (NoMethodError)
I want to use profession like:
<div>Profession name: <%= profession[p.name] %></div>
<div>Description: <%= profession[p.name]['descr'] %></div>
How can I make profession work with as one [name] and as two [name][descr] parameters?
You start with an empty hash:
{}
Then, for every Profession record, you assign profession[p.name] = p.unique_profession. Assuming that unique_profession is a Fixnum, that means you get this:
{
'ProfessionName1' => 1,
'ProfessionName2' => 2
}
and so on.
You can't assign sub-keys to Fixnum - it's not a hash. You might instead want one of the following data structures (I'll follow the structure with the code to create it):
{
'ProfessionName1' => {
'descr' => 'Description of Profession 1',
'created_at' => '2016-05-08T22:33:38.093753Z'
},
'ProfessionName2' => {
'descr' => 'Description of Profession 2',
'created_at' => '2015-04-09T21:23:33.093753Z'
}
}
profession = Hash.new
Profession.all.each do |p|
profession[p.name] = Hash.new
profession[p.name]['descr'] = p.description
profession[p.name]['created_at'] = p.created_at
end
or simply an array of hashes containing every property:
[
{
'name' => 'ProfessionName1',
'descr' => 'Description of Profession 1',
'created_at' => '2016-05-08T22:33:38.093753Z'
},
{
'name' => 'ProfessionName2',
'descr' => 'Description of Profession 2',
'created_at' => '2015-04-09T21:23:33.093753Z'
}
]
profession = []
Profession.all.each do |p|
profession << {
'name' => p.name,
'descr' => p.description,
'created_at' => p.created_at
}
end
If you want to use hashes you'll need to store 'unique_profession' into a new key.
profession = Hash.new
Profession.all.each do |p|
profession[p.name] = []
profession[p.name]['unique'] = p.unique_profession
profession[p.name]['descr'] = p.description # problem
profession[p.name]['created_at'] = p.created_at # problem
end
Then you can do this (but note the output will be a number, the contents of unique_profession):
<div>Profession name: <%= profession[p.name]['unique'] %></div>
<div>Description: <%= profession[p.name]['descr'] %></div>
Finally, I'd recommend using symbols instead of strings (as that's the Ruby way):
profession = Hash.new
Profession.all.each do |p|
profession[p.name] = []
profession[p.name][:unique] = p.unique_profession
profession[p.name][:descr] = p.description
profession[p.name][:created_at] = p.created_at
end
Then
<div>Profession name: <%= profession[p.name][:unique] %></div>
<div>Description: <%= profession[p.name][:descr] %></div>
On the other hand you could just store and use the Profession instances directly.
I have a Model called Example that accepts_nested_attributes_for NestedExample.
When I create a new Example Model I can also create NestedExamples:
params = { :name => 'Example 1', :nested_example_attributes => { :name => 'Nested Example 1' } }
Example.find_or_create_by_name params
This is all working fine. However, I rather than creating a new NestedExample every time, I would like Rails to perform a find_or_create_by_name on the NestedExample model, so that in the above situation, if there is already a NestedModel with a name of Nested Example 1, it will be used, rather than a new instance of NestedExample with the same name.
My current result:
params_1 = { :name => 'Example 1', :nested_example_attributes => { :name => 'Nested Example 1' } }
params_2 = { :name => 'Example 2', :nested_example_attributes => { :name => 'Nested Example 1' } }
example_1 = Example.find_or_create_by_name params_1
example_2 = Example.find_or_create_by_name params_2
puts example_1.nested_example.id == example_2.nested_example.id # Should be true
I have the following:
#array.inspect
["x1", "x2", "adad"]
I would like to be able to format that to:
client.send_message(s, m, {:id => "x1", :id => "x2", :id => "adad" })
client.send_message(s, m, ???????)
How can I have the #array output in the ??????? space as a ids?
Thanks
{:id => "x1", :id => "x2", :id => "adad" } is not a valid hash since you have a key collision
it should look like:
{
"ids": ["x1", "x2", "x3"]
}
Update:
#a = ["x1", "x2", "adad"]
#b = #a.map { |e| {:id => e} }
Then you can do b.to_json, assuming you have done require "json" already
Well ordinarily you could do something like this:
Hash[#array.collect{|i| [:id, i]}]
But that will result in {:id => "adad"} because the first element will punch all the rest: hashes in ruby have unique keys. So I don't think there's a super awesome way to do this offhand.