Redis-Objects in rails saves as String, not array - ruby-on-rails

I am using the redis-objects gem to store simple info
class Purchase < ActiveRecord::Base
include Redis::Objects
hash_key :user_purchases, :marshal => true, :global => true # "hash" is taken by Ruby
def self.add_user_end(fb_id,item_id)
if self.user_purchases[fb_id]
a = Array.new
a << candidate_id
self.user_purchases[fb_id] = a
else
new_a = self.user_purchases[fb_id]
new_a << item_id
self.user_purchases[fb_id] = new_a
end
end
end
I'm creating a method to collect user_purchases as a hasy_key, keyed by a users fb id. I would imply like to see a collection of ids when I use Purchase.user_purchases["2"] => [1,23,563,2]
I am running into a problem with Redis::Object where I can only save this as a string: Why?
1.9.3-p125 :050 > Purchase.user_purchases["6"].class
=> String
1.9.3-p125 :051 > Purchase.user_purchases["6"]
=> "\u0004\b[\u0006I\"\v543555\u0006:\u0006ET"
Answer:
My Initialization file was missing require 'redis/list'
require 'redis'
require 'redis/objects'
require 'redis/hash_key'
require 'redis/list'
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)

My Initialization file was missing require 'redis/list'
require 'redis'
require 'redis/objects'
require 'redis/hash_key'
require 'redis/list'
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)

Related

“Uninitialized constant” error when trying to create Client

I am working on dashing dashboard and trying to add a Jira widget.In the widget code it is trying to create and initialize a Client object. As shown in code below
require 'Jira'
SCHEDULER.every '5m', :first_in => 0 do |job|
client = Jira::Client.new({
:username => ENV['Talal'],
:password => ENV['Talal123'],
:site => "http://192.168.99.100:32768",
:auth_type => :basic,
:context_path => "/jira"
})
But as I gets to this line client = Jira::Client.new. An exception occurs which states that uninitialized constant Jira::Client.
I believe the gem you should be using is jira-ruby. Once you install it, Bundler should automatically require it for you, meaning if you're in a Rails environment, you shouldn't need to do require 'Jira'.
If you don't want it required application-wide, BTW, you should add this to your Gemfile:
gem 'jira-ruby', require: false
# then in your scheduler, you have to explicitly require it as before:
require 'jira-ruby'
SCHEDULER.every '5m', :first_in => 0 do |job|
client = Jira::Client.new({
:username => ENV['Talal'],
:password => ENV['Talal123'],
:site => "http://192.168.99.100:32768",
:auth_type => :basic,
:context_path => "/jira"
})
Additional information here

How to speed up sitemap_generator with parallel gem

I am trying to speed up sitemap_generator by adding parallelization via the parallel gem. I have the following code but my groups aren't getting written to the public/sitemaps directory. I am thinking it's due to lambdas getting executed in a different space in parallel. Any feedback would be helpful. Thanks!
#!/usr/bin/env ruby
require 'rubygems'
require 'sitemap_generator'
require 'benchmark'
require 'parallel'
require 'random-word'
SitemapGenerator::Sitemap.default_host = "http://localhost"
a = lambda {
SitemapGenerator::Sitemap.group(:filename => :biz, :sitemaps_path => 'sitemaps/biz/') do
(1..1000).each do |index|
url = "/#{RandomWord.adjs.next}/#{RandomWord.nouns.next}"
add url, :priority => 0.8
end
end
}
b = lambda {
SitemapGenerator::Sitemap.group(:filename => :wedding_ugc, :sitemaps_path => 'sitemaps/ugc') do
(1..1000).each do |index|
url = "/#{RandomWord.adjs.next}/#{RandomWord.nouns.next}"
add url, :priority => 0.8
end
end
}
#working example
# SitemapGenerator::Sitemap.default_host = "http://localhost"
# SitemapGenerator::Sitemap.create(:compress => false) do
# group(:filename => :biz, :sitemaps_path => 'sitemaps/biz/') do
# (1..1000).each do |index|
# url = "/#{RandomWord.adjs.next}/#{RandomWord.nouns.next}"
# add url, :priority => 0.8
# end
# end
# end
puts Time.now
Parallel.each([a,b]){|job| job.call()}
puts Time.now
I got this working and posted the solution on github here
Here is the code incase the url gets broken.
SitemapGenerator::Sitemap.create(:compress => false, :create_index => false) do
group1 = lambda {
group = sitemap.group(:filename => :group1, :sitemaps_path => 'sitemaps/group1') do
Record.find_each do |record|
add '/record/path'
end
end
group.sitemap.write unless group.sitemap.written? #write if not full
}
# group2 like above...
Parallel.each([group1, group2], :in_processes => 8) do |group|
group.call
end
end
#regenerate the index sitemap xml file because I couldn't figure out how to track it with multiple processes
SitemapGenerator::Sitemap.create(:compress => false) do
Dir.chdir(sitemap.public_path.to_s)
xml_files = File.join("**", "sitemaps", "**", "*.xml")
xml_file_paths = Dir.glob(xml_files)
xml_file_paths.each do |file|
add file
end
end

how do i get message list with Gmail Api?

i want to access list of messages
Object:
2.0.0-p481 :008 > g.gmail_api.users.messages.list
=> # < Google::APIClient::Method:0x41c948c ID:gmail.users.messages.list >
i'm new in this API and unable to get how do i use Gmail API.
Thanks
# Google
gem "omniauth-google-oauth2"
gem "google-api-client"
in my model
def query_google( email )
self.refresh_token_from_google if self.expires_at.to_i < Time.now.to_i
#google_api_client = Google::APIClient.new(
application_name: 'Joggle',
application_version: '1.0.0'
)
#google_api_client.authorization.access_token = self.access_key
#gmail = #google_api_client.discovered_api('gmail', "v1")
# https://developers.google.com/gmail/api/v1/reference/users/messages/list
# Now that we instantiated gmail, we can take the category (messages) and the method
# You can also add parameters if you wish to do so:
# #calendar_events = google_api_client.execute(
# :api_method => #calendar.events.list,
# :parameters => {
# "calendarId" => current_user.email,
# 'timeMin' => date.to_s,
# 'timeMax' => max_date.to_s
# # 'items' => [{'id' => current_user.email}]
# },
# :headers => {'Content-Type' => 'application/json'}
# )
#emails = #google_api_client.execute(
api_method: #gmail.users.messages.list,
parameters: {
userId: "me",
# searching messages based on number of queries:
# https://developers.google.com/gmail/api/guides/filtering
q: "from:" + email.to_s
},
headers: {'Content-Type' => 'application/json'}
)
count = #emails.data.messages.count
Rails.logger.error count
{count: count, last_emails: get_three_emails} if count > 0
end
for reference : https://github.com/google/google-api-ruby-client/issues/135
Not a ruby expert but that looks like a method, can you call () it? I imagine you've gone through steps to setup authentication, etc? the messages.list() function should be able to be called without any parameters generally (well, you may need to specify a userId, which you can just use "me" for to get the authenticated user).

Ruby on Rails always pointing local redis Server

I am using Redis with my ruby on rails application, To map Ruby object with Redis using redis-objects, dm-core and dm-redis-adapter. Below are the code snipts
Gemfile
gem 'redis-objects'
gem "dm-core", "~> 1.2.1"
gem "dm-redis-adapter"
/config/initializers/redis.rb
// LOCAL REDIS SERVER
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
// REMOTE REDIS SERVER
#Redis.current = Redis.new(:host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>')
Model.rb
DataMapper.setup(:default, {:adapter => "redis"})
class User
include Redis::Objects
include DataMapper::Resource
include ActiveModel::Validations
include ActiveModel::Conversion
# datamapper fields, just used for .create
property :id, Serial
property :name, String
property :email, String
property :des, Text
def id
1
end
end
User.finalize
It's working fine for local redis server. Why app always pointing local redis, Even when providing remote host and port?
SOLVED: checkout my answer.
As per Question:
// LOCAL REDIS SERVER
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
// REMOTE REDIS SERVER
#Redis.current = Redis.new(:host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>')
Model.rb
DataMapper.setup(:default, {:adapter => "redis"})
In above code, I am overloading Redis configuration in User model.
In that case, I need to write remote configuration in model as well.
DataMapper.setup(:default, {:adapter => "redis", :host => '<VM IP>', :port => <VM PORT>, :password => '<PASSWORD>'})
Redis.current is a method which always gives a new connection if the instance variable #current is empty. See https://github.com/redis/redis-rb/blob/master/lib/redis.rb#L19
def self.current
#current ||= Redis.new
end
Try assigning Redis.new to some other global like $redis. This should mostly fix your issue.

Sidekiq worker not able to write to database or log file

I'm building an app on Herokou and Redis that sends an SMS messages for every row in an input CSV file which contains the mobile phone number. The message is sent using Twilio in a sidekiq worker shown below. The problem is that even though the SMS is being sent for all the rows in the CSV, the database write (TextMessage.create) and log write (puts statement) only executes for one row in the CSV. There is one Sidekiq worker spawned for each row in the CSV file. It seems like only one Sidekiq worker has I/O (DB, file) access and it locks it from the other Sidekiq workers. Any help would be appreciated.
sidekiq worker:
require 'sidekiq'
require 'twilio-rb'
class TextMessage < ActiveRecord::Base
include Sidekiq::Extensions
def self.send_message(number, body, row_index, column_index, table_id)
puts "TextMessage#send_message: ROW INDEX: #{row_index} COLUMN INDEX: #{column_index} TABLEID: #{table_id} BODY: #{body} PHONE: #{number}"
Twilio::Config.setup :account_sid => 'obfuscated', :auth_token => '<obfuscated>'
sms = Twilio::SMS.create :to => number, :from => '+17085555555', :body => body + ' | Sent: ' + Time.now.in_time_zone('Central Time (US & Canada)').strftime("%m/%d/%Y %I:%M%p Central")
TextMessage.create :to => number, :from => '+17085555555'
ImportCell.add_new_column(table_id, row_index, column_index, "Time Sent", Time.now.in_time_zone('Central Time (US & Canada)').strftime("%m/%d/%Y %I:%M%p Central"))
end
end
call to sidekiq worker:
TextMessage.delay_until(time_to_send, :retry => 3).send_message(phone, 'Scheduled: ' + time_to_send.in_time_zone('Central Time (US & Canada)').strftime("%m/%d/%Y %I:%M%p Central"), row_index, column_index, table.id)
column_index += 1
Heroku Procfile
worker: bundle exec sidekiq -C config/sidekiq.yml
sidekiq.yml
:verbose: false
:concurrency: 3
:queues:
- [default, 5]
config/initializers/redis.rb:
uri = URI.parse(ENV["REDISTOGO_URL"])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Sidekiq.configure_server do |config|
database_url = ENV['DATABASE_URL']
if(database_url)
ENV['DATABASE_URL'] = "#{database_url}?pool=25"
ActiveRecord::Base.establish_connection
end
end
I am one of the people who commented on your question, just fixed it!
You are using .create which SideKiq seemed to not like, so I tried using .new and then .save which made it work! I think it has to do with .create not being thread safe or something of the sort, but I honestly have no idea.
Non Working code:
class HardWorker
include Sidekiq::Worker
def perform(name, count)
puts 'Doing some hard work!'
UserInfo.create(
:user => "someone",
:misc1 => 0,
:misc2 => 0,
:misc3 => 0,
:comment => "Made from HardWorker",
:time_changed => Time.now
)
puts 'Done with hard work!'
end
end
Working code:
class HardWorker
include Sidekiq::Worker
def perform(name, count)
puts 'Doing some hard work!'
a_row = UserInfo.new(
:user => "someone",
:misc1 => 0,
:misc2 => 0,
:misc3 => 0,
:comment => "Made from HardWorker",
:time_changed => Time.now
)
a_row.save
puts 'Done with hard work!'
end
end

Resources