Return Array in a helper method - ruby-on-rails

Why can't I return an array in a helper method?
def childrenOf(a)
#children = Post.find_by_parent_id(a.id)
return #children
end
Thanks in advance

You can.
Use find_all_by_parent_id instead.
And you don't need the second line.
The following is enough.
def childrenOf(a)
#children = Post.find_all_by_parent_id(a.id)
end

In Rails 3 instead of using find_all_by use where:
def childrenOf(a)
#children = Post.where(:parent_id => a.id)
end

Related

Rails dynamic where clause

I have a where clause being called based off of a json object from a form. The object has a series of boolean values for locales which will be used to find Venues within the given locale.
Is there a better way to write a series of queries than having a long string built off of boolean values? Any help in the right direction would be greatly appreciated. Thanks!
hard_worker.rb
def build_locales
filters = []
filters.push 'locale_north' if #lead.locale_north
filters.push 'locale_south' if #lead.locale_south
filters.push 'locale_east' if #lead.locale_east
filters.push 'locale_west' if #lead.locale_west
return filters
end
def build_string
filters = build_locales
s = ''
filters.each_with_index do |f, i|
s+= "#{f} = true"
s+= " OR " if i < filters.size - 1
end
end
def perform(lead_id)
#venues = Venue.where(receive_all: true).or(Venue.where(build_string))
// ... more code ...
end
where clauses are chainable so you can easily do a lot of querying if you need to with an approach like this.
#venues = Venue.all
#venues = #venues.where(receive_all: true)
filters.each do |filter|
#venues = #venues.or(Venue.where(filter.to_sym: true))
end
# after all of this you can just return #venues
#venues

How to get all records of all parent records

I'm needing to create a select box for a form where I list all child records of all parents. How do I do this in my controller? I'm thinking the answer below, but its returning "undefined method nil:NilClass"
before_action :get_children
def get_children
#parents = current_user.parents.all
#children = #parents.children.all
end
#parents is an array so the children of that array would be nil.
So you would have to use some type of loop like:
def get_children
children = []
#parents = current.user.parents.all
#parents.each do |child|
children << child
end
return children
end
Something like this oughta work.
If you want an array:
#children = #parents.map(&:children).flatten.uniq
If you want an ActiveRecord::Relation (assuming your model is called Thing, and each thing belongs_to parent):
#children = Thing.where(parent_id: #parents)
You can do the following:
def get_children
#parents = current_user.parents.all
#children = Children.where(parent_id: #parents.pluck(:id).uniq)
end

Ruby: How to make custom DSL accept variables

I have this class:
class Items
def initialize &block
(block.arity < 1 ? (instance_eval &block) : block.call(self)) if block_given?
end
def button_id button_id=nil
unless #button_id.present?
raise "button_id must be supplied" if button_id.nil?
#button_id = button_id
end
#button_id
end
end
Now, when I do this it works:
Items.new do
button_id 1
end
But when I do this, it fails because I think it is not on the same scope:
#button = Button.find(params[:button_id]
Items.new do
button_id #button.id
end
How can fix this to take arguments outside the scope?
Thanks!
Try this:
class Items
def self.dsl
new.tap do |item|
yield item
end
end
def button_id(button_id)
#button_id = button_id
end
end
#button = Button.find(params[:button_id])
item = Items.dsl do |item|
item.button_id(#button.id)
end
puts item.inspect
Turns out all I needed to do was to pass the arguments to the block like this:
Items.new do |item|
item.button_id #button.id
end
Less beautiful DSL but works.
I don't think this is the right use case of DSL, when you can simply assign the attributes by arguments.
class Item
attr_accessor: :button_id
def initialize(args)
button_id = args[:button_id]
end
end
Another problem is in your usage. The instance would be of little value if you don't assign it to a variable
item = Item.new button_id: button_id

Create Hash iterating an array of objects

I have an object that has attributes name and data, among others. I want to create a hash that uses the name as the key and the data (which is an array) as the value. I can't figure out how to reduce the code below using map. Is it possible?
def fc_hash
fcs = Hash.new
self.forecasts.each do |fc|
fcs[fc.name] = fc.data
end
fcs
end
Use Hash[]:
Forecast = Struct.new(:name, :data)
forecasts = [Forecast.new('bob', 1), Forecast.new('mary', 2)]
Hash[forecasts.map{|forecast| [forecast.name, forecast.data]}]
# => {"mary"=>2, "bob"=>1}
def fc_hash
forecasts.each_with_object({}) do |forecast, hash|
hash[forecast.name] = forecast.data
end
end
I always use inject or reduce for this:
self.forecasts.reduce({}) do |h,e|
h.merge(e.name => e.data)
end
Hash[*self.forecases.map{ [fc.name, fc.data]}.flatten]
With Ruby 2.1 and onward, you could also use Array#to_h
self.forecasts.to_h { |forecast| [forecast.name, forecast.data] }

Using a method while looping through an array in ruby

I am using ruby-aaws to return Amazon Products and I want to enter them into my DB. I have created a model Amazonproduct and I have created a method get_amazon_data to return an array with all the product information. When i define the specific element in the array ( e.g. to_a[0] ) and then use ruby-aaws item_attributes method, it returns the name I am searching for and saves it to my DB. I am trying to iterate through the array and still have the item_attributes method work. When i don't define the element, i get this error: undefined method `item_attributes' for #Array:0x7f012cae2d68
Here is the code in my controller.
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each { |name|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = #arr.item_attributes.title.to_s
}
EDIT: Code in my model to see if that helps:
class Amazonproduct < ActiveRecord::Base
def self.get_amazon_data(r)
resp = Amazon::AWS.item_search('GourmetFood', { 'Keywords' => 'Coffee Maker' })
items = resp.item_search_response.items.item
end
end
Thanks for any help/advice.
I'm not familiar with the Amazon API, but I do observe that #arr is an array. Arrays do not usually have methods like item_attributes, so you probably lost track of which object was which somewhere in the coding process. It happens ;)
Try moving that .item_attributes call onto the object that supports that method. Maybe amazonproduct.get_amazon_data(:r), before its being turned into an array with to_a, has that method?
It's not quite clear to me what your classes are doing but to use #each, you can do something like
hash = {}
[['name', 'Macbook'], ['price', 1000]].each do |sub_array|
hash[sub_array[0]] = sub_array[1]
end
which gives you a hash like
{ 'name' => 'Macbook', 'price' => 1000 }
This hash may be easier to work with
#product = Product.new
#product.name = hash[:name]
....
EDIT
Try
def create
#arr = Amazonproduct.get_amazon_data( :r ).to_a
#arr.each do |aws_object|
#amazonproduct = Amazonproduct.new(params[:amazonproducts])
#amazonproduct.name = aws_object.item_attributes.title.to_s
end
end

Resources