i am trying to display all the residents on a pdf and their dependents, but the dependents doesn't have a stand they are identified by the foreign key user_id of the resident. e.g resident1.id = 5 --- dependent3.user_id = 5 mean dependent3 belongs to resident1, and therefore if i want to display the dependent stand what should i do and i would like to display all the residents and their dependents and the stand information for dependents to be the stand info of the resident the dependent belong to. now my information should be inside a hash so it can generate my pdf file..
my code is
data = []
c = 1
residents.each do |r|
data <<{"Fullname" => r.firstname, "Lastname" => r.lastname, "Street-Number" => r.stand.street_no, "street Name" => r.stand.streetname} if r.stand || r.user_id = r.id
end
remember my dependents and residents are in the same table but residents doesn't have the user_id foreigh key only the dependent have it.
and my output only display the information of the residents who have stands not the dependents.
please anyone who is willing to help.cause i dont know if i can but an if statement inside a hash like:
residents.each do |r|
data <<{"Fullname" => r.firstname, "Lastname" => r.lastname} if r.stand || r.user_id = r.id{"Street-Number" => r.stand.street_no, "street Name" => r.stand.streetname}
Assuming that .stand.street_no, etc. is valid even if .stand is false (since it could be false and still be called if the r.user_id == r.id part is true), then the following would work:
data = residents.map do |r|
hash = { "Fullname" => r.firstname, "Lastname" => r.lastname }
hash.merge!({ "Street-Number" => r.stand.street_no, "street Name" => r.stand.streetname}) if r.stand || r.user_id == r.id
hash
end
Explanation:
Iterate through each resident object and build a hash that contains values that we know will be used.
Conditionally merge! in the extra keys if the if clause is true.
Return the hash.
Doing this in a map eliminates the need to predeclare the data array, nor push the hash on each pass through the loop.
data = []
residents.each do |r|
tmp_hash = {"Fullname" => r.firstname, "Lastname" => r.lastname}
if r.stand || r.user_id = r.id
tmp_hash.merge({"Street-Number" => r.stand.street_no, "street Name" => r.stand.streetname})
end
data << tmp_hash
end
Related
I'm trying some code to find an attribute with a time value that is less than current time.
If I have current_time = Time.now, how do I find it using where such as:
Outage.where("end_time < current_time") # this doesn't work.
There are many ways to do that via placeholder.
Using ? Placeholder
You can use ? as a placeholder in a query condition.
User.where('users.name = ?', 'John')
With multiple placeholders:
User.where('users.name = ? AND users.last_name = ?', 'John', 'Smith')
Using Named Placeholder
User.where('first_name = :first_name', { :first_name => 'John' })
With multiple placeholder:
values = { :first_name => 'John', :last_name => 'Smith'}
conditions = 'first_name = :first_name AND last_name = :last_name'
User.where(conditions , values)
Noted that order does not matters. The following code would work correctly since we have already named those placeholders.
values = { :last_name => 'Smith', :first_name => 'John'}
conditions = 'first_name = :first_name AND last_name = :last_name'
User.where(conditions , values)
References: Using Named Placeholders in Ruby
You can use placeholder - ? and then pass the value, like this:
Outage.where('outages.end_time < ?', current_time)
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
I have two different models that I need to join together in a selection query and list on a page. They share all of attributes that I'll need to reference in the view (created_at, updated_at, name, etc), and I want them in order of creation. I'm wondering what the most efficient way to do this is? I was thinking of performing the selection query on each object individually and adding the relevant parts into a common array but that seems inefficient.
For example if my models were Dogs and Cats and I wanted a list of all dogs and cats of age 5, I was thinking something like
#pets = []
dogs = Dogs.where(:age => 5)
cats = Cats.where(:age => 5)
dogs.each do |dog|
hash = {"id" => dog.id, "name" => dog.name, "created_at" => dog.created_at }
#pets.push(hash)
end
cats.each do |cat|
hash = {"id" => cat.id, "name" => cat.name, "created_at" => cat.created_at }
#pets.push(hash)
end
But is that the best way to do it? also, I'm not sure how to sort the finished array in this example according to date created...
try this
dogs = Dogs.where(:age => 5)
cats = Cats.where(:age => 5)
#pets = (dogs + cats).sort_by { |pet| pet.created_at }
OR if you want your hashes still, use map to create the array of hashes
dogs = Dogs.where(:age => 5)
cats = Cats.where(:age => 5)
#pets = (dogs + cats).sort_by do |pet|
pet.created_at
end.map do |pet|
{ "id" => dog.id, "name" => pet.name, "created_at" => pet.created_at }
end
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'
I have a form that handles four different types of facets of the same form. In my SQL column, I have the four different attributes.
Only one of them is going to have data in it.
Distribution =>
zip_code: nil
me_topic: nil
sex: nil
age: nil
In order to differentiate between them, I wanted to set up a case statement, and add a dynamic attribute to the create call :
#type = case params[:type]
when "zip" then ":zip_code"
when "interest" then ":me_topic"
when "sex" then ":sex"
when "age" then ":age"
end
#cur_item = Distribution.new(#type => params[:value])
# Unfortunately, this is not the proper way to create a dynamic attribute
#distribution = #email.distributions.create(params[:distributions])
What is the proper syntax for completing this statement?
Declare a method called type_map
def type_map params
##type_map ||= {
"zip" => :zip_code,
"interest" => :me_topic,
"sex" => :sex,
"age" => :age
}
{ ##type_map[params[:type]] => params[:value]
end
Now you can use the map as follows:
#distribution = #email.distributions.create(type_map(params))
This is what I went with, but feel free to best my answer.
#cur_item = case params[:type]
when "zip" then {:zip_code => params[:value]}
when "interest" then {:me_topic => params[:value]}
when "sex" then {:sex => params[:value]}
when "age" then {:age => params[:value]}
end
#distribution = #email.distributions.create(#cur_item)
Well, one way to improve your code (what you posted in your answer) would be to factor out the repeated params[:value] as follows:
key = case params[:type]
when "zip" then :zip_code
when "interest" then :me_topic
when "sex" then :sex
when "age" then :age
end
#cur_item = { key => params[:value] }
#distribution = #email.distributions.create #cur_item