updating column for all users method - ruby-on-rails

I am trying to create a method that will update a column for all my users at a specific time. I am doing this with the 'whenever' gem but I don't really know where to place the method.
My Users table has a column with :grades that I want to update based on another method (grade). In the rails console, when I do:
user.update(:grades => user.grade)
This works fine. When I define the method within the rails console that I want like this:
def update_grades(users)
users.each do |user|
user.update(:grades => user.grade)
end
end
#users = User.all
update_grades(#users)
This works as well and updates the grades for all the users.
The problem is that I don't know where to place this method for it to work in my scheduler. I tried putting it in the user.rb model file but then when I call update_grades(#users) it gives me this error:
NoMethodError: undefined method `update_grades' for main:Object
I changed it to remove the (#users) and try to call update_grades or #users.update_grades neither of these work and I get this error:
NoMethodError: private method `update_grades' called for #<User::ActiveRecord_Relation:0x007fbb753b1b58>
Any ideas where I can place the method so that I can call update_grades(#users) or update_grades?

You can make it a class method on User
class User
def self.update_grades
all.each do |user|
user.update(:grades => user.grade)
end
end
end
This can be called as User.update_gradesa
Consider wrapping it in a transaction to speed it up:
def self.update_grades
transaction do
all.each do |user|
user.update(:grades => user.grade)
end
end
end

Related

Unsplash object method available from the console but not from the view

This one baffles me. I've banged my head on it for a couple of weeks now and am getting nowhere. Sorry if it's obvious, I'm still a rails newbie ish...
The app is making an API call to the Unsplash pictures service.
As such the application_helper has the following method:
def show_photo(size)
#photo = Unsplash::Photo.random(query:"cars")[:urls][size.to_sym]
end
the view has the following:
<%= image_tag(show_photo('small'), height: "220", width:"220") %>
And that displays fine.
The issue is when I want to pull some other methods from the oject. I've added another method in the application helped like this:
def show_author
#photo.user.name
end
and the corresponding view:
Photo by: <%= show_author %>
I then get this error:
undefined method `user' for #
However when calling the method in the Rails console it works fine:
#photo = Unsplash::Photo.random(query:"cars")
=> #<Unsplash::Photo:0x00000004fcf950 #attributes=#<OpenStruct id="CKeoh-
90U3E", created_at="2017 .......
2.3.0 :003 > #photo.user.name
=> "Florian Schneider"
What do I need to do to have the user.name available in the view?
Thanks a lot in advance,
Rodolphe
#photo is not the photo, it looks like you're calling some meta-data on #photo with [:urls][size.to_sym] and you can't call .user on top of that meta-data.
You're essentially saying Unsplash::Photo.random(query:"cars")[:urls][size.to_sym].user
You might want to do the following:
def photo
#photo ||= Unsplash::Photo.random(query:"cars")
end
def resized_photo(size)
photo[:urls][size.to_sym]
end
def photo_author_name
photo.user.name
end
btw #photo ||= is memoizing the API call so you're not making the same call multiple times.

ActiveRecord is not reloading nested object after it's updated inside a transaction

I'm using Rails 4 with Oracle 12c and I need to update the status of an User, and then use the new status in a validation for another model I also need to update:
class User
has_many :posts
def custom_update!(new_status)
relevant_posts = user.posts.active_or_something
ActiveRecord::Base.transaction do
update!(status: new_status)
relevant_posts.each { |post| post.update_stuff! }
end
end
end
class Post
belongs_to :user
validate :pesky_validation
def update_stuff!
# I can call this from other places, so I also need a transaction here
ActiveRecord::Base.transaction do
update!(some_stuff: 'Some Value')
end
end
def pesky_validation
if user.status == OLD_STATUS
errors.add(:base, 'Nope')
end
end
end
However, this is failing and I receive the validation error from pesky_validation, because the user inside Post doesn't have the updated status.
The problem is, when I first update the user, the already instantiated users inside the relevant_posts variable are not yet updated, and normally all I'd need to fix this was to call reload, however, maybe because I'm inside a transaction, this is not working, and pesky_validation is failing.
relevant_users.first.user.reload, for example, reloads the user to the same old status it had before the update, and I'm assuming it's because the transaction is not yet committed. How can I solve this and update all references to the new status?

Undefined method update when updating a record in Rails

I'm having trouble parsing through a hash and then saving certain parts to my database. I'm able to iterate through it to get to the information that I need. My problem is updating the record in my database. I'm trying to update an existing record in my database based on if the country code for each country matches the country code in the XML parse.
In my controller I have:
class CountriesController < ApplicationController
def index
#countries = Country.all
travel_alerts = request_data('http://travel.state.gov/_res/rss/TAs.xml')
travel_warnings = request_data('http://travel.state.gov/_res/rss/TWs.xml')
# Sets warnings
warnings_array = travel_warnings["rss"]["channel"]["item"]
warnings_array.each do |warning|
#country = Country.find_by(code: warning["identifier"].strip)
#country.update(title: warning["title"],
description: warning["description"])
end
end
end
...
I've tried using .update and .save, but neither works. When I try update I get:
undefined method `update' for nil:NilClass
Does the update method need to be explicitly defined in the Country model? If so, what's the best way to have access to the parsed information since that's being done in the controller?
It raises an error, because Country by given code was not found, then find_by returns nil, on which update method does not exist.
Instead of find_by executrun find_by! - you should get ActiveRecord::RecordNotFound error
If it is expected some countries do not exist put your update statement within if block
if #country
#country.update ...
end

Custom id column issue

in my listing model i setup a method
def set_listing_number
listing_number="TM#{created_at.year}#{id}"
end
i have a couple of records that was created before i ran the migration to create the listing_number column. i wanted to update all the records at once but keep receiving this error.
here's the code that i ran that produce the error in console verifying if the method . it works i cannot save the assignment.
listing_number=listing.set_listing_number
=> "TM2014574"
2.0.0-p247 :003 > listing_number.save
NoMethodError: undefined method `save' for "TM2014574":String
i tried a couple with no success , that i also found here like this one
Listing.all.each{|n| n.update_attributes(:listing_number =>"TM#{n.created_at.year})}
the question how do i update the previous record at once. probably it's pretty basic but can't figure it out. thanks
# This method in Listing Model
def set_listing_number
listing_number="TM#{created_at.year}#{id}"
end
# In controller
Listing.all.each do |listing|
listing.set_listing_number
listing.save
end
or you can refactor this as
Listing.all.each do |listing|
listing.update listing_number: "TM#{listing.created_at.year}"
end
You're calling save on a string. You need listing.save in your code.

undefined method `fql_query' for nil:NilClass

With the koala gem I am trying to count checkins for a page. I am using rails.
In my user.rb I have a method for getting a new connection to the Facebook graph:
class User < ActiveRecord::Base
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
end
end
In my school.rb I have a method for counting the checkins:
class school < ActiveRecord::Base
def count_checkins(name)
checkins = #facebook.fql_query("SELECT checkins FROM page WHERE name = #{name}")
end
end
And I am calling it from the view like this:
<%= #school.count_checkins(#school.name) %>
But I get the following error:
undefined method `fql_query' for nil:NilClass
Dont really understand why I get this error, any help would be wonderful.
It looks like you haven't actually created the #facebook object inside your School model. We'd need to see the rest of your school.rb file to know for sure. I'd suggest you create the object inside your School.initialize() method like so:
def initialize(oauth_token)
unless oauth_token.nil?
#facebook = Koala::facebook::API.new(oauth_token)
end
end
In order for this to work, you'll need to pass the desired oauth_token to your School.new() call. Then you'll have one #facebook object for each School.
Edit
After looking at the gist, I realized that you had actually intantiated a User object, and called the facebook method on that. That is actually the better way to do it. The problem is, you're using #current_user, which would have to be setup as a property of the school model. You probably meant to use the helper function current_user instead.
def count_checkins(name)
u = current_user
u.#facebook.fql_query("SELECT checkins FROM page WHERE name = #{name}")
end
Try that and see what happens. At the very least, you should get a different error message.
Edit 2
So, now I'm thinking the current_user function should be called in controller code, not model code. This is because the current user is something that doesn't really exist except as part of an active request. Therefore, we should take User u as a parameter to the count_checkins function like so:
def count_checkins(name, u)
u.facebook.fql_query("SELECT checkins FROM page WHERE name = #{name}")
end
You'll need to change the code where you call count_checkins() too:
count_checkins(name, current_user)
That should do it. Let's see!

Resources