How to pass methods to Ruby Map - ruby-on-rails

I have the following code:
wedding = Wedding.where(location_id: user_params[:locationId])
wedding.map(&:guests).each do |member|
user_ids << member.ids
end
In my case :guests is a active record table, but I have a couple that I would like to pass thru map to generate the user_ids
So it would be array of methods like this, that I would like to pass: [guests, bride, etc etc]
It would be even better if I could pass the whole array, but otherwise if I can step through the array of methods that would be great too.
Any ideas?
EDIT:
I'm trying this with no luck.. I get: NameError (wrong constant name guests):
roles = ["guests"]
wedding = Wedding.where(location_id: user_params[:locationId])
roles.each do |role|
clazz = Kernel.const_get(role)
wedding.map(&:clazz).each do |member|
user_ids << member.ids
end
end

Below, i pass an array of methods to members of the array weddings:
weddings = Wedding.where(location_id: user_params[:locationId])
# array with methods you're interested in
methods=[:guests, :bride]
# looping through the weddings array
weddings.each do |wedding|
# looping through the methods array
methods.each do |method|
# for each wedding, passing every method to the wedding
members=wedding.public_send(method)
members.each do |member|
# storing the values
user_ids << member.ids
end
end
end

Related

For array of ActiveRecord objects, return array of their attributes

#matched = [1, 2, 3]
Where each integer represents the id of an ActiveRecord object in the Inventory class. As a next step, I want to look at each of those objects and obtain the email of the parent User, but I'm not sure how to do it. Ideally I'd write something like:
Inventory.where(id: #matched).user.email
Because certainly, this statement would work if I only had a single id to look up. Since that doesn't work, I'm instead doing this
#email = []
#matched.each do |i|
#email << Inventory.find_by_id(i).user.email
end
Just wondering if there's an easier way.
Thanks!
If you only need the email addresses then you can use the pluck method:
Inventory.where(id: #matched).joins(:user).pluck("users.email")
class Inventory
def self.with_ids(ids)
sql = #matched.map{|id| "id = #{id}"}.join(" OR ")
where(sql)
end
def parent_email
user.email
end
end
Inventory.with_ids(#matched).map(&:parent_email)

Rails loop through records in model

I have 2 hstore columns (parameters and keys) defined in my PostgeSQL database. I want to get a list of keys and have defined a method for it in the model:
def self.keys_list
logs = self
list = Log.column_names - %w{id parameters extras}
logs.each do |log|
log.parameters.present? ? list << log.parameters.keys : list << []
log.extras.present? ? list << log.extras.keys : list << []
end
list = list.flatten.uniq
return list
end
But when I try using it, I get the following error:
NoMethodError: undefined method `each' for #<Class:0x00000004b630b0>
Can anyone suggest where the error is or how to do it some other way?
ActiveRecord::Base does not define an .each method. You need to add in a call to all, like so:
all.each do |log|
#...
end
This should make both Log.keys_list and Log.where(name: "Peeyush").keys_list work.

Rails iterate over objects array

I want to do something like this
#groups = Community::GroupMember.where(:member_id => current_user.id)
user_ids = []
#groups.each do |group|
user_ids << #group.community_group_members.where(:group_id => group.id).pluck(:member_id)
end
But I get error NoMethodError - undefined method `community_group_members' I think im not iterating #groups properly the way I want.
You should have:
user_ids << group.community_group_members.pluck(:member_id)
(group instead of #group). It's because inside each block, the element of your array is represented by local variable (which is unprefixed) instead of instance variable (prefixed by #). So #group instance variable is unset and thus evaluated to nil, which doesn't respond to community_group_members method.
Also, I deleted your where clause, since it's reduntant - you're already doing this in group.community_group_members call.
#groups = Community::GroupMember.where(:member_id => current_user.id)
user_ids = []
#groups.each do |group|
user_ids << group.community_group_members.where(:group_id => group.id).pluck(:member_id)
end
Does using the block variable group instead of #group work?
Assuming you have two models Community::Group and Community::GroupMember with associations has_many :community_group_members and belongs_to :community_group respectively, your first line:
#groups = Community::GroupMember.where(:member_id => current_user.id)
returns an array of Community::GroupMember instances, i.e. group members, not groups.
To get the associated groups you could use map:
#group_members = Community::GroupMember.where(member_id: current_user.id)
#groups = #group_members.map { |group_member| group_member.community_group }
or a join:
#groups = Community::Group.joins(:community_group_members).where(community_group_members: { member_id: current_user.id })
You can now retrieve the member_ids with:
user_ids = Community::GroupMember.where(group_id: #groups).pluck(:member_id)

Rails Search with query

I want to filter jobs on the parameter passed onto the model, currently search works flawlessly without query passed into the model, but when I type query it doesn't return anything. How can I perform this query with query and criteria.
results << model.with_query(query).where(criteria). any idea would be really appreciated.
module Refinery
class SearchEngine
# How many results should we show per page
RESULTS_LIMIT = 100
# Perform search over the specified models
def self.search(query, job_region, job_division, country, job_type, page = 1)
results = []
Refinery.searchable_models.each do |model|
criteria = {:job_region => job_region,
:job_division => job_division,
:country => country,
:job_type => job_type
}.select { |key, value| value.present? }
if query.present?
results << model.with_query(query).where(criteria)
else
results << model.limit(RESULTS_LIMIT).where(criteria)
end
end
results.flatten[0..(RESULTS_LIMIT - 1)]
end
end
end
The problem here is that the method .with_query(qry) returns an Array. You want to do chain-scoping, so you must use scopes that returns ActiveRecord::Relation objects.
model.with_query(query)
# returns an Array
model.with_query(query).where(criteria)
# calling .where on an Array object => NoMethodError
model.where(criteria)
# returns an ActiveRecord::Relation
model.where(criteria).with_query(query)
# calls the query on an AR::Relation object, which is doable
Short version: Change this:
results << model.with_query(query).where(criteria)
To this:
results << model.where(criteria).with_query(query)

Create an array from data received

I am trying to learn how to get data via a screen scrape and then save it to a model. So far I can grab the data. I say this as if I do:
puts home_team
I get all the home teams returned
get_match.rb #grabbing the data
require 'open-uri'
require 'nokogiri'
module MatchGrabber::GetMatch
FIXTURE_URL = "http://www.bbc.co.uk/sport/football/premier-league/fixtures"
def get_fixtures
doc = Nokogiri::HTML(open(FIXTURE_URL))
home_team = doc.css(".team-home.teams").text
end
end
Then i want to update my model
match_fixtures.rb
module MatchFixtures
class MatchFixtures
include MatchGrabber::GetMatch
def perform
update_fixtures
end
private
def update_fixtures
Fixture.destroy_all
fixtures = get_fixtures
end
def update_db(matches)
matches.each do |match|
fixture = Fixture.new(
home_team: match.first
)
fixture.save
end
end
end
end
So the next step is where I am getting stuck. First of all I need to put the home_team results into an array?
Second part is I am passing matches through my update_db method but that's not correct, what do I pass through here, the results of the home_team from my update_fixtures method or the method itself?
To run the task I do:
namespace :grab do
task :fixtures => :environment do
MatchFixtures::MatchFixtures.new.perform
end
end
But nothing is saved, but that is to be expected.
Steep learning curve here and would appreciate a push in the right direction.
Calling css(".team-home.teams").text does not return the matching DOM elements as an array, but as a single string.
In order to obtain an array of elements, refactor get fixture into something like this:
get_teams
doc = Nokogiri::HTML(open(FIXTURE_URL))
doc.css(".team-home.teams").map { |el| el.text.strip }
end
This will return an array containing the text of the elements matching your selector, stripped out of blank and new line characters. At this point you can loop over the returned array and pass each team as an argument to your model's create method:
get_teams.each { |team| Fixture.create(home_team: team) }
You could just pass the array directly to the update method:
def update_fixtures
Fixture.destroy_all
update_db(get_fixtures)
end
def update_db(matches)
matches.each {|match| Fixture.create(home_team: match.first) }
end
Or do away with the method all together:
def update_fixtures
Fixture.destroy_all
get_fixtures.each {|match| Fixture.create(home_team: match.first) }
end

Resources