downcase remove duplicates rails save database - ruby-on-rails

I'm trying to do a simple downcase and remove duplicates in rails. Also save to the database.
Tag.all.each do |tag|
tag_name = tag.name.downcase!
tag_name.uniq!
tag.save!
end
Error
NoMethodError: undefined method `uniq!' for nil:NilClass
Also tried with pluck
tag_name = Tag.pluck(:name)
tag_name.each do |tag|
name = tag.downcase!
name.uniq!
end
Error
NoMethodError: undefined method `uniq!' for nil:NilClass

Used group_by to find filter query.
found_tags = Tag.all.group_by { |tag| tag.name.downcase }
found_tags.each do |key, val|
if found_tags[key].count > 1
tag_to_keep = val.shift
val.each do |t|
t.taggings.update_all(tag_id: tag_to_keep.id)
t.destroy!
end
tag_to_keep.update(name: tag_to_keep.name.downcase)
end
end

Related

undefined method `+' for nil:NilClass - Values are not null

I am trying to create a method that loops through some objects and if a certain attribute is true, adds to the cost of the lesson to the money received, but keep getting the error undefined method `+' for nil:NilClass.
Here is the piece of code (the line producing the error start #activity.update_attribute):
def show
#activity = Activity.find(params[:id])
#participants = Participant.all.where(:activity_id => #activity.id).map(&:user_id).uniq
#all_participants = Participant.all.where(:activity_id => #activity.id)
#all_participants.each do |a_participant|
if a_participant.paid
#activity.update_attribute(:money_received, #activity.money_received + #activity.cost)
end
end
#users = Array.new
#participants.each do |participant|
#users.push(User.find(participant))
end
end
And here is a screenshot from my database to show that neither is a null value:
Here is the error message that I get when running the application:
Any help would be greatly appreciated
Many thanks

Undefined new_record? Ruby Rails

I am trying to check if the domain host url record exist in the domain table before creating it again, but I am getting this error:
undefined method `new_record?' for #<Domain::ActiveRecord_Relation:0x007f320ed8af80>
The class GetMeta is a service object that is getting initialize when a user enter a URL in a form and click submit. I am taking the URL from the form and calling MetaInspector with it to get more meta informations.
The first part (if) new_record method is working perfectly fine, but is creating duplicate values in the domain table. I tried to create a conditional logic, but I am having this bug that I don't know how to fixed.
class GetMeta
include ActiveModel::Model
def initialize(url)
#url = url
end
def new_record
page = MetaInspector.new(#url)
#domain = Domain.where(:host => page.host)
if new_record?
Domain.create! do |url|
url.root_url = page.root_url
url.scheme = page.scheme
url.host = page.host
url.links.build(url: page.url, title: page.best_title, description: page.description)
end
else
Link.create! do |link|
link.url = page.url
link.title = page.best_title
link.description = page.description
end
end
end
private
def new_record?
#domain.new_record?
end
end
The problem is described by an error. Let's see:
undefined method `new_record?' for
#<Domain::ActiveRecord_Relation:0x007f320ed8af80>
The problem is the line
#domain = Domain.where(:host => page.host)
This returns an ActiveRecord relation instead of single record.
You should take a .first or .last.
#domain = Domain.where(:host => page.host).last
That's the fix, but let's see how can we improve the code.
We can use method exists? which is defined in ActiveRecord Relation (docs: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F)
if Domain.exists?(host: page.host)
Link.create! do |link|
link.url = page.url
link.title = page.best_title
link.description = page.description
end
else
Domain.create! do |url|
url.root_url = page.root_url
url.scheme = page.scheme
url.host = page.host
url.links.build(url: page.url, title: page.best_title, description: page.description)
end
end
This way we don't need instance variable #domain and helper method new_record?
You are calling an instance method from within an instance method. So you need to specify which instance you are referring to. You need to use 'self'. So instead of just calling 'new_record?', try calling self.new_record?

undefined method `empty?' for nil:NilClass how to avoid it

Hi Together I've got this code:
#coursesFound = #user.available_courses
#courses = []
for course in #coursesFound do
#courseInGroups = course.user_groups
for group in #courseInGroups do
#group = UserGroup.find group.id
if #group.users.map { |u| u.id }.include? #user.id
#courses << course
break
end
end
end
# Wenn ein Kurs keiner Gruppe hinzugefĆ¼gt wurde
if #courseInGroups.empty?
#courses << course
end
on my debian vm it works fine but on my live system I got this error:
undefined method `empty?' for nil:NilClass
How can I avoid this?
If this #coursesFound = #user.available_courses returns an empty activerecord relation.
Then this won't execute
for course in #coursesFound do
#courseInGroups = course.user_groups
for group in #courseInGroups do
#group = UserGroup.find group.id
if #group.users.map { |u| u.id }.include? #user.id
#courses << course
break
end
end
end
Which means when you get here #courseInGroups is nil
if #courseInGroups.empty?
#courses << course
end
So your quick fix would be
if #courseInGroups && #courseInGroups.empty?
#courses << course
end
You can use the try method to Avoid this error:
#courseInGroups.try(:empty?)
This won't throw an error if #courseInGroups was nil.
And don't forget blank? when using rails. Here you find a good overview of all methods with or without rails.
I did not analyze your code, it's just for you, me and others that do not use this methods often, mix them up and then come here - just to remember: empty? is not blank?.
You need to properly initialize your object as well.
#courseInGroups = course.user_groups || []
You won't get nil:NilClass error any more if you initialize properly.
To get rid of nil:NilClass error you can use other answer. like try etc.
You can put the ? before the dot of the empty:
if #courseInGroups?.empty

Why group calculation fields do not show up in query result?

I have query like this:
query = Link.select('url, max(created_at) as created_at, count(*) as url_count').group(:url).order('url_count desc, created_at asc')
Sample results of query.results.first:
2.2.0 :002 > query.first
=> #<Link id: nil, url: "http://1", created_at: "2015-03-10 16:43:54">
Why there is no url_count here, even though I know it is.
2.2.0 :003 > query.first.url_count
=> 17
The count is there all along but the model to_s method does not know about it.
The to_s method which is used when your console logs the result from query.first is defined somewhere in activerecord and it uses the attributes defined for the model in the database. Since your attribute is only defined for this particular instance of Link not for the model Link.
I found this quite interesting. Below is a description of how the message displayed in your console is constructed. It starts out in the gem active_attr with these 3 methods displayed below:
def inspect
attribute_descriptions = attributes.sort.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
separator = " " unless attribute_descriptions.empty?
"#<#{self.class.name}#{separator}#{attribute_descriptions}>"
end
# ...
def attributes
attributes_map { |name| send name }
end
# ...
def attributes_map
Hash[ self.class.attribute_names.map { |name| [name, yield(name)] } ]
end
the method attributes_names is defined in the gem activerecord
def attribute_names
#attribute_names ||= if !abstract_class? && table_exists?
column_names
else
[]
end
end
# ...
def column_names
#column_names ||= #connection.columns(#table_name).collect { |c| c.name }
end
And that is why your count does not show up.
If you really want it to show up in your console you could override the inspect method and add it there.

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.

Resources