Rails get from view table column name and value of select - ruby-on-rails

I now, that question could be non good for so, but need help:
In my rails haml view i have such code:
%table.table.table-striped
= form_tag :admin_other_price_upload do
%tr
- #csv.first.length.times do |n|
%th
= n + 1
%br/
=select_tag "s"+(n+1).to_s, options_for_select([["Брэнд", "Brand"], ["Артикул","Article"], ["Наименование","Descr"], ["Цена","Price"], ["Количество","Quantity"], ["Дополнительно","Other"], ["Поле кроссов","Cross"]]), :prompt => 'Все', :id => "select-value"
*********************************
so as you can see i'm setting to all select's name like s(n+1) and value one from list. But how can i get them both in controller method? I need it becouse i have dynamic table. I will explain it on example:
So i have table with select's
name = s1 (value = Brand) | name = s2 (value = Price)
so i need in controller to get not only that s1 => Brand, but also get this 1 from s1
So if param look's like
[
s1 => {Brand}
]
I need to get for my calculation s1 not value, but s1 as string (simple i need to find in params, which value has Brand and select it as a value)
So for Brand i need to select s1, and set as s1 value s1, how could i do it?

I may have understood you, but not sure.
# let's say your params hash is like:
params = { :action => 'show', :controller => 'articles',
:s1 => 'Article', :s2 => 'Brand', :s3 => 'Price', ... }
brand_param = params.select{ |key, value| value == 'Brand' }
# => { :s2 => 'Brand' }
which_s_is_brand = brand_param.keys.first.to_s
# => 's2'

Related

Rails - Iterate thru Multiple Arrays

I'm looking for a more DRY way to iterate through some code. I have a User model and I want to keep count of certain Users in a ReportRecord model (for reporting).
I have a defined list of values of User.names that I want to record (i.e. "Jan", "Lisa", "Tina"). How can I make this code more DRY as the list is much longer than three values?
#users = User.all
#users.each do |u|
# this part repeats with different names
quantity = u.where("name = ?", "Jan").count
ReportRecord.create(:user_id => u.id, :name => "Jan", :quantity => quantity)
# repeated code with different name
quantity = u.where("name = ?", "Lisa").count
ReportRecord.create(:user_id => u.id, :name => "Lisa", :quantity => quantity)
# repeated code with different name
quantity = u.where("name = ?", "Tina").count
ReportRecord.create(:user_id => u.id, :name => "Tina", :quantity => quantity)
end
I would sum all users first (1 query instead of 3):
quantity_by_name = User.select(:name).where(name: %w(Jan List Tina))
.group(:name).sum(:quantity)
#=> { 'Lisa' => 1, 'Jan' => 2, 'Tina' => 3 }
quantity_by_name.each do |name, quantity|
ReportRecord.create(name: name, quantity: quantity)
end
names = %w(Jan List Tina)
names.each do |name|
count = User.where(name: name).count
ReportRecord.create(name: name, quantity: count) # I don't understand `u.id`
end

How to generate symbols inside a loop in ruby

I have a section of a web app that passes a hash of values like this for each of the order_items in an order.
Like this:
def example_method
values = {
amount_1: order_items.first.unit_price,
item_name_1: order_items.first.unit_price,
quantity_1: order_items.first.quantity,
amount_2 order_items.second.unit_price,
item_name_2: order_items.second.unit_price,
quantity_2: order_items.second.quantity,
}
end
I'm trying to generate a solution where I have a variable like n = 1 and generate the symbols for each order_item using n like this:
def example_method
values = {
n=1
order_items.each do |item|
:"amount_#{n}" => item.unit_price,
:"item_name_#{n}" => item.name,
:"item_number_#{n}" => item.id,
:"quantity_#{n}" => item.quantity,
n += 1
end
end
I tried this syntax outside of the loop and it works perfectly to generate the symbols using the variable, the problem is that I get a Syntax Error when the code is inside the loop:
How can I achieve this behavior inside my code?
What am I missing?
#edit
Edit for a proposed solution:
values = {
# The rest of static values on the hash...
}
n = 1
items = order_items.each do |item|
{
"amount_#{n}".to_sym => item.unit_price,
"item_name_#{n}".to_sym => item.printer.name,
"item_number_#{n}".to_sym => item.id,
"quantity_#{n}".to_sym => item.quantity,
}
n += 1
end
values.merge(items)
please try this
n=1
order_items.each do |item|
"amount_#{n}".to_sym => item.unit_price,
"item_name_#{n}".to_sym => item.name,
"item_number_#{n}".to_sym => item.id,
"quantity_#{n}".to_sym => item.quantity,
n += 1
end
#edit
items = order_items.each do |item|
"amount_#{n}".to_sym => item.unit_price,
"item_name_#{n}".to_sym => item.name,
"item_number_#{n}".to_sym => item.id,
"quantity_#{n}".to_sym => item.quantity,
n += 1
end
old_hash.merge(items)
maybe you could running this and merge with outside hash
edit 2
you can install gem 'pry' to a better debug solution. For more info check this videos RailsCast Pry Debug
values = {
# The rest of static values on the hash...
}
n = 1
items = order_items.each do |item|
{
"amount_#{n}".to_sym => item.unit_price,
"item_name_#{n}".to_sym => item.printer.name,
"item_number_#{n}".to_sym => item.id,
"quantity_#{n}".to_sym => item.quantity,
}
n += 1
end
binding.pry # this will able a ruby shell prompt and you can execute your code and analyse the values
values.class # in pry prompt
items.class # in pry prompt
values.merge(items)
#edit 3
#items = {}
order_items.each do |item|
#items = {
"amount_#{n}".to_sym => item.unit_price,
"item_name_#{n}".to_sym => item.printer.name,
"item_number_#{n}".to_sym => item.id,
"quantity_#{n}".to_sym => item.quantity}
values = values.merge(#items)
n += 1
end
You can't use the new symbol syntax with interpolation, it has to be the old one. Also, mutating an index inside the loop is a bad practice in general in Ruby, use each_with_index instead:
order_items.each_with_index do |item, index|
{
:"amount_#{index}" => item.unit_price,
:"item_name_#{index}" => item.name,
:"item_number_#{index}" => item.id,
:"quantity_#{index}" => item.quantity,
}
end
Syntax as such
amount_1: 1
is not valid as a key value needs to be wrapped in {} to be a hash or when passed as arguments to a method call.
Also since you're interpolating a string you can do the following
:"amount_#{n}" => 1
If what you're aiming to do is return an array of hashes then you want to do the following
n=0
order_items.map do |item|
n += 1
{
:"amount_#{n}" => item.unit_price,
:"item_name_#{n}" => item.name,
:"item_number_#{n}" => item.id,
:"quantity_#{n}" => item.quantity,
}
end

create a specific hash (dynamic)

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},{}......]

How to find a hash key containing a matching value for a hash having array of values

I have situation like this:
clients = {
"yellow"=>[{"client_id"=>"2178","price" => 1},{"client_id" => "2282","price" => 2}],
"orange"=>[{"client_id"=>"2180","price" => 1},{"client_id" => "2283","price" => 3}],
"red"=>[{"client_id"=>"2178","price" => 1},{"client_id" => "2282","price" => 3}],
"blue"=>[{"client_id"=>"2180","price" => 1},{"client_id" => "2283","price" => 1}]
}
I need to get the key(s) with client ids => [2282,2178] and get the lowest key value based on price.
How can I achieve this?
res = []
client.each{|k, v|
res << k if v.detect{|hash| hash["client_id"] == "2282"}
}
res
#=> ["red", "yellow"]
NOTE
This answer is for OPs original question that required finding keys that contained "client_id" = 2282. I have not updated my answer as OP changed the requirement quite lazily.

Search ignoring certain blank parameters

I have a simple search action that has 3 parameters and a where method to search a model. If I search and some of the parameters are nil, it will not return the records I want. I want it to search the database by only using the parameters that are not nil/blank. So if only one category is entered and sent in the parameters, I want my controller to ignore the other two parameters. However, if the other parameters are present, I want them to be included in the search.
I've tried many approaches but I can't get it to work properly. Here's my code.
hash = []
cat = :category_id => params[:category_id]
col = :color_id => params[:color_id]
brand = :brand_id => params[:brand_id]
if params[:category_id].present?
hash += cat
end
if params[:color_id].present?
hash += col
end
if params[:brand_id].present?
hash += brand
end
#results = Piece.where(hash).preload(:item).preload(:user).group(:item_id).paginate(:page => params[:page], :per_page => 9)
I've put the variables into strings and hashs, called to_a, joined them with (","). Nothing works.
Thanks
Try this code.
criteria = { :category_id => params[:category_id], :color_id => params[:color_id],
:brand_id => params[:brand_id] }.select { |key,value| value.present? }
#results = Piece.where(criteria).preload(:item).preload(:user).group(:item_id).
paginate(:page => params[:page], :per_page => 9)

Resources