Ruby On Rails : create nested Array - ruby-on-rails

I'm trying to make an array of objects, let's call it "categories", and I want each object in this array to have an array called "items" within it, so the result will be something like this:
[category:id=11, name="beer", items[1,2,3,4]]
I've tried this code:
#category ||= Array.new
#categoryItems ||= Array.new
#venues.categories.enabled.each do |category|
#category.push(category)
#categoryItems.push(category.items.enabled)
end
but I don't know how to name the items inside so I can use them in json afterward. How can I do this?

You can try create hash.
#category ||= Array.new
#venues.categories.enabled.each do |category|
hash = {}
hash[:category][:id] = category.id
hash[:category][:name] = category.name
hash[:category][:items] = category.items.enabled.pluck(:id).join(',')
#category << hash
end

Related

Rails: group_by then map children

I have a method that looks like this:
def categorised_templates
template_categories.all_parents.map do |cat|
cat.templates.by_brand(id).group_by(&:category)
end
end
Which returns something like this:
[{"Communications":["#<Template:0x00007fef0efcdd48>","#<Template:0x00007fef0efcdb90>"]},{"Beta":["#<Template:0x00007feefe1bb008>"]}]
How can I render the Template objects into JSON just like the categories? I need to maintain the group_by hierarchy.
Turns out it was easy enough. This change:
def categorised_templates
arr = template_categories.all_parents.map do |cat|
cat.templates.by_brand(id).group_by(&:category)
end
arr.map { |cat| cat.transform_values!(&:to_s) }
end
Returns this result.
[{"Communications":"[#<Template id: 2, ...]"}]

Iterating through an lazy load array

I'm tryin to build an array of hashes and then iterate through.
If I use the code below
#elements = [{:profile_id=>"123"}, {:profile_id=>"456"}]
#categories = Array.new
#elements.each do |element|
category = Category.find_by_profile_id(element[:profile_id])
#categories.push(category)
end
It will find the last object and it will add to the array. However I would like to fetch all the records with that id.
I have been trying the code bellow
#elements = [{:profile_id=>"123"}, {:profile_id=>"456"}]
#categories = Array.new
#elements.each do |element|
category = RootCategory.where(profile_id: element[:profile_id])
#categories.push(category)
end
#response
[#<ActiveRecord::Relation [#<Category id: "123", ...">, #<Category id: "123", ..."> #<ActiveRecord::Relation [#<Category id: "456", ...">, #<Category id: "456", ...">]>]
I can't iterate through the returned array. If I try
#categories.each do |t|
puts t.name
end
#Prints
#Category
#Category
This is mostly because you are abusing each for mapping. ActiveRecord::Base#where returns a Relation object (without a loss of generality it might be considered an array here). What you need is Enumerable#flat_map:
elements = [{:profile_id=>"123"}, {:profile_id=>"456"}]
#categories =
elements.flat_map do |element|
RootCategory.where(profile_id: element[:profile_id])
end
or, even better, avoid multiple queries, since where happily accepts an array:
#categories =
RootCategory.where(profile_id: elements.map { |e| e[:profile_id] })
The latter is basically executing:
RootCategory.where(profile_id: [123, 456])
retrieving categories for all the profiles specified.

Create array and append key and value in each

I want to create a array and then to insert values for each key (key should be the value from each). But seems to not working. This is my code.
#options = %w(Services Resources)
#images = []
#options.each do |value|
#images[value] << Media::Image.where(type: "Media::#{value.singularize}Image")
end
#images is an array so referencing an element in it should be #images[Integer] and value is a string (in the first iteration it's "Services" and in the second "Resources"). Instead, what would work for you is Hash:
#options = %w(Services Resources)
#images = {}
#options.each do |value|
#images[value] = Media::Image.where(type: "Media::# {value.singularize}Image")
end
#images is a Array, Array can not use as a Hash.
Maybe you want create a Hash like this
#images = Hash.new {|h,k| h[k]=[]}

Rails - Fetch results on the basis of number of params in query string

I am working on an events application where i want to filter events depending on the 3 parameters location or starts_at or ends_at in the query string. There can be any one, two or all the parameters in the query string. In i use if-else statement i need to make 6 cases which will make my code clumsy. Rather i am thinking to implement something this way:
class EventsController < ApplicationController
def index
unless params.empty?
unless params[:location].nil?
#events = Event.where("location = ?", params[:location])
end
unless params[:starts_at].nil?
unless #events.empty?
#events = #events.where("start_date = ?", params[:start_date])
else
#events = Event.where("Date(starts_at) = Date(?)", params[:starts_at])
end
end
unless params[:ends_at].nil?
unless #events.empty?
#events = #events.where("end_date = ?", params[:end_date])
else
#events = Event.where("Date(ends_at) = Date(?)", params[:ends_at])
end
end
end
end
end
But this code doesnt work since where query doen not work on an array. Can someone suggest me some solution for this..
You should be able to pass your params hash directly to where, and it will form the correct SQL based on the keys and values of that hash:
Event.where(params)
An example in the console:
1.9.3p194 :001 > puts Example.where(:location => 'here', :started_at => '2012-08-13').to_sql
SELECT "examples".* FROM "examples" WHERE "examples"."location" = 'here' AND "examples"."started_at" = '2012-08-13'
Try Following
def index
unless params.empty?
where_array, arr = [], []
if params[:location]
where_array << "location = ?"
arr << params[:location]
end
if params[:starts_at]
where_array << "start_date = ?"
arr << params[:starts_at]
end
if params[:ends_at]
where_array << "end_date = ?"
arr << params[:ends_at]
end
#events = arr.blank? ? [] : Event.where([where_array.join(" AND "), *arr])
end
end

How to append to a nil object in Rails iterating through a loop?

#preComments = Comment.where(:resource_hash => resource_hash).sort(:created_at.desc).all
#preComments.each do |comment|
u = ::User.find_by_id comment.user_id
p u
#comments << #preComments
p "HERE!!!!!"
end
That's my code, but #comments isn't defined so I get an error:
You have a nil object when you didn't expect it! You might have
expected an instance of Array. The error occurred while evaluating
nil.<<
If I create an array first, then my view can't read it. So how do I do this?
The problem is that the first time you iterate, you want to create the #comments array (containing that item), but all subsequent times you want to push that item onto the existing array. There's probably a more elegant way to do this, but I generally just do this:
#comments ? #comments = [comment] : #comments << comment
Create the array before the loop using #comments = [], then in the loop make sure you're using #comments << comment, not #comments << #preComments.
I think you must initialize array
#preComments = Comment.where(:resource_hash => resource_hash).sort(:created_at.desc).all
#comments = []
#preComments.each do |comment|
u = ::User.find_by_id comment.user_id
p u
#comments << comment
p "HERE!!!!!"
end
or when loop is finished then pass values of #preComments to #comments
#preComments = Comment.where(:resource_hash => resource_hash).sort(:created_at.desc).all
#preComments.each do |comment|
u = ::User.find_by_id comment.user_id
p u
p "HERE!!!!!"
end
#comments = #preComments

Resources