Rails iterate over objects array - ruby-on-rails

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)

Related

How to pass methods to Ruby Map

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

Error deleting record in console ruby on rails

I am trying to delete a record using the console. I have a model for "User". I tried several methods in the console:
a = User.where(:id => '18')
a.destroy
a.delete
User.where(:id => '18').destroy
User.where(:id => '18').delete
Using all of these methods, I got the same error: "Wrong number of arguments (0 for 1)"
Does anyone know what I am doing wrong?
Thx!
Try:
a = User.find(18)
a.destroy
When we use where, result will be ActiveRecord::Relation, means multiple records, on which you can't call destroy directly. You will need to call destroy by iterating over the result.
users = User.where(:id => 18)
users.each do |user|
user.destroy
end
I can add something here, The issue with your code that you are passing string while it expects an integer 'Number'
Your code should be as the following:
a = User.where(:id => 18).first
a.destroy
Without using first array of object will be returned and you can't use destroy method directly on it, in case you don't want to add first then your code should be like:
a = User.where(:id => 18)
a.each do |obj|
obj.destroy
end

Active Record query when some conditions are absent

I have the following hash conditions for retrieving products from the database:
#products = Product.where(category: #category, color: params[:color], brand_id: params[:brand], size: params[:size]).
Is there a way to get the query result when one or more of the conditions are not supplied, for example
if params[:color] is absent, how can i retrieve the products with the other conditions?, or how can i restructure the conditions to achieve this?
I'm going to base myself on techvineet's answer (editing was becoming messy).
Try this:
# This line throws away the :action and :controller arguments
params.except!(:action, :controller) # notice the ! now
params.delete_if {|k,v| v.nil?} # throw out any empty args
params[:category] = #category
#products = Product.where(params)
You could also use something like this:-
params.except(:action, :controller)
params[:category] = #category
#products = Product.where(params)
You can try Periscope gem
Or Ransack
You can build your query using conditions like this:
product_scope = Product.where(:category => #category)
product_scope = product_scope.where(:color => params[:color]) if params[:color]
# (...)
#products = product_scope.all
That way, only the valid and present conditions are being added to the scope. Or you could build a hash with your options in a similar way and add only the keys with valid params, then call Product.where(conditions_hash).all

Rails Array Conditions Query

I've written the following method to combine the References of Sections model and it's children:
def combined_references
ids = []
ids << self.id
self.children.each do |child|
ids << child.id
end
Reference.where("section_id = ?", ids)
end
But section.combined_references returns the following error:
Mysql2::Error: Operand should contain 1 column(s): SELECT `references`.* FROM `references` WHERE (section_id = 3,4)
It seems to have collected the correct values for ids, have I structured the query incorrectly?
Transform last line to:
Reference.where(section_id: ids)
and it should produce:
SELECT `references`.* FROM `references` WHERE section_id IN (3,4)
And you can shorten your code by one line with :
ids = []
ids << self.id
to
ids = [self.id]
it's invalid statement
WHERE (section_id = 3,4)
correct would be
WHERE (section_id in (3,4))
Please use:
Reference.where(:section_id => ids)
You can try something like this instead:
def combined_references
ids = self.children.map(&:id).push(self.id)
Reference.where(section_id: ids)
end
You can also query the database with:
Reference.where("section_id in (?)", ids)
The following has the most readability in my opinion:
def combined_references
Reference.where(section_id: self_and_children_ids)
end
private
def self_and_children_ids
self.children.map(&:id).push(self.id)
end

Rails Given an array of objects from a db, is there a way to get an item in the array w/o having to rehit the db?

Given:
#votes (user_id, option_id)
If do: #project.votes I get all the votes for that project.
If I then want to see what the current user voted for I have to do:
Votes.where(:user_id => current_user.id).first
This is a record that's already in the #project votes query. Is there a way I can find the record in that first query w/o having to rehit the db?
Thanks
You can just use the regular ruby Enumerable#select method:
#votes = project.votes.all
# ... other code ...
current_user_votes = #votes.select{ |v| v.user_id == current_user.id }
This will return an array of all the user's votes for the project. If the user is only allowed one vote, and you want a single value, not an array, just use .first like so:
#votes = project.votes.all
# ... other code ...
current_user_vote = #votes.select{ |v| v.user_id == current_user.id }.first

Resources