Display variables as plain text in rails - ruby-on-rails

In my rails app I save some data as below.
def send_share_company(address, cid, from, council_id)
co = Council.find_by(id: council_id)
c = Company.find_by(id: cid)
#a = address.split(',')
#f = from
n = Notification.find_by(id: 'ad4e3718-0689-413b-8a52-96887e0d2aba')
message =eval(n["body"])
from = Email.new(email: 'noreply#my.network', name: "my Network")
subject = + cl["title"] + ' - Event of the Week: ' + c["name"]
to = Email.new(email: a.to_s)
content = Content.new(type: 'text/html', value: message)
mail = Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
pp sg.client.mail._("send").post(request_body: mail.to_json) unless Rails.env.staging?
end
I used another form to add message to the database. Then I retrieve it using,
n = Notification.find_by(id: 'ad4e3718-0689-413b-8a52-96887e0d2aba')
My message as below. This is the data which I have save in database.
Hello,
{#f} thought you should take a look at the company, #{c["name"]}.
When I display this in my app it displays as above. But I want display plain text.Is there way to do this?

Related

Add attachment to email with SendGrid using rails

I've created a hello_world method which sends an email with Sendgrid. I am trying to include an attachment. I've found the following line in another stackoverflow answer: mail.attachments['test.txt'] = File.read("#{Rails.root}/public/test.txt")
This however generates the following error:
Completed 500 Internal Server Error in 17ms (ActiveRecord: 3.4ms)
TypeError - no implicit conversion of String into Integer:
app/controllers/messages_controller.rb:32:in `hello_world'
app/controllers/messages_controller.rb:65:in `create'
Mailing code in controller:
def hello_world(company, message)
from = Email.new(email: "test+#{current_user.auth_token}#example.com")
to = Email.new(email: 'hello#pim.gg')
subject = 'TEST from dev'
content = Content.new(type: 'text/plain', value: "#{company.email} #{current_user} #{current_user.first_name} #{current_user.last_name} #{message.text}")
mail = SendGrid::Mail.new(from, subject, to, content)
mail.attachments['test.txt'] = File.read("#{Rails.root}/public/test.txt")
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers
end
According to documentation of sendgrid-ruby gem adding-attachments should be like this:
attachment = SendGrid::Attachment.new
attachment.content = Base64.strict_encode64(File.open(fpath, 'rb').read)
attachment.type = 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet'
attachment.filename = fname
attachment.disposition = 'attachment'
attachment.content_id = 'Reports Sheet'
mail.add_attachment(attachment)

How to make one default receiver be able to see the other receivers mail ids in ActionMailer rails

I am sending mails to multiple receivers at a time. I needed one default receiver to be able to see the ids of other receivers on his mail. And the other receivers are in BCC. I tried by setting the default mail to to: field and other receivers to bcc:. It didn't work. Following is my code.
def newequip_matches_wanted
#default_mail = "mail#mymail.com"
#system_email = SystemEmail.find_by(title: 'Equipment matches WantedEquipment')
#subject = #system_email.try(:subject).to_s
#subject = "Equipment matches WantedEquipment" if #subject.blank?
#equipment = Equipment.last
x = Equipment.last.try(:category_id)
y = WantedEquipment.pluck(:category_id)
a = Equipment.last.try(:sub_category_id)
b = WantedEquipment.pluck(:sub_category_id)
y.include?(x) && b.include?(a)
if true
#receiver = WantedEquipment.where(sub_category_id: "#{a}", status: 2).pluck(:email)
mail(bcc: #receiver, to: #default_mail, subject: #subject)
end
end
What am I missing here?
Question is updated.
You missed storing the subject into #subject and also you have syntax error in second code for mail
def mail
#subject = "This is Demo subject"
#default_mail = "mail#mymail.com"
#receiver = Model.where(status: 2).pluck(:email)
mail(bcc: #receiver, to: #default_mail, subject: #subject)
end
Here is a reference

Screen Scraping with nokogiri

I am a full stack ruby developer.I am trying to scrape to the data from the website and i am successfully able to get the data.But the problem is that next time when i fetched the data i just want to fetch only new data the i don't want to overwrite all the the data in the database.
I just want to add new record which added recently.But i am not able to find any solution for that how to do it with minimum queries and minimum code.
Here is my code which i am using for scrapping:
client = Mechanize.new
index_page = client.get('https://www.google.com/')
document_page_index = Nokogiri::HTML::Document.parse(index_page.body)
page_no_merchant = document_page_index.css('.pagination.pagination-centered ul li:nth-last-child(2) a').text.to_i
1.upto(page_no_merchant) do |page_number|
client.get("https://www.google.com/buy-gift-cards?page=#{page_number}") do |page|
document = Nokogiri::HTML::Document.parse(page.body)
document.css('.product-source').each do |item|
merchant_name= item.children.css('.name').text.gsub("Gift Cards", "")
puts merchant_name
href = item.css('a').first.attr('href')
puts href
image_url=item.children.css('.img img').attr('data-src').text.strip
puts image_url
image_url=URI.parse(image_url)
#merchant=Merchant.create!(name: merchant_name , image_url:image_url)
first_page = client.get("https://www.google.com#{href}")
document_page = Nokogiri::HTML::Document.parse(first_page.body)
page_no = document_page.css('.pagination.pagination-centered ul li:nth-last-child(2) a').text.to_i
1.upto(page_no) do |page_number_giftcard|
type1=[]
card_page = client.get("https://www.google.com#{href}?page=#{page_number_giftcard}")
document_page = Nokogiri::HTML::Document.parse(card_page.body)
document_page.xpath('//table/tbody/tr[#class="toggle-details"]').collect do |row|
row.at("td[2] ul").children.each do |typeli|
type = typeli.text.strip if typeli.text.strip.length != 0
type1 << type if typeli.text.strip.length != 0
end
value = row.at('td[3]').text.strip
value = value.to_s.tr('$', '').to_f
puts value
per_discount = row.at('td[4]').text.strip
per_discount = per_discount.to_s.tr('%', '').to_f
puts per_discount
final_price = row.at('td[5] strong').text.strip
final_price = final_price.to_s.tr('$', '').to_f
puts final_price
puts '******************************'
#giftcard=Giftcard.create(card_type:1, card_value:value, per_off:per_discount, card_price: final_price, merchant_id: #merchant.id)
end
#giftcard.update_attribute()
end
end
end
end
Thank you in advance.
Basically you are saving all data, by doing this.
#merchant=Merchant.create!(name: merchant_name , image_url:image_url)
You can try something like find_or_create_by.
#merchant=Merchant.find_or_create_by(name: merchant_name , image_url:image_url)
http://apidock.com/rails/v4.0.2/ActiveRecord/Relation/first_or_create
http://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_create_by

How to manage API requests in multiusers app in Rails?

In my app when user add object it execute one API request to third party site. For single user is ok to send the request immediately. But API calls are limited by 3 per second. So, when qtt of users will increase it'll be a trouble. I suggested that ActiveJob + Sidekiq will do the work, but how to get results when job is done?
My code for one user:
controller.rb
def create
wall = get_request(code_constructor({params for constructor },[]))
end
module CommonMods
def code_constructor(meth_name, meth_params, code)
param_str = []
meth_params.each_pair do |name, value|
param_str << '"' + name.to_s + '":'+ value.to_s
end
param_str = param_str.join(',')
code << meth_name + '({' + param_str + '})'
end
def get_request(code)
i = 0
result = []
while i < code.size
part_code = code.slice(i, i + 25)
if part_code.size >1
part_code = part_code.join(',')
else
part_code = part_code[0]
end
url='https://api.site.com/method/'
uri = URI.parse(url)
parameters = {'code' => "return [#{part_code}];"}
response = Net::HTTP.post_form(uri, parameters)
result = result + JSON.parse(response.body)['response']
i += 25
end
result
end
end
How to execute get_request method in queue with code param and proceed with received response in the controller? Or maybe it have different way to make it?

Sending HTML email using gmail API in ruby

I am creating a ruby script and it should do the above. Over the day I was trying to crack I way to send an HTML email to a selected number of emails addresses. There is no clear documentation on how I should do, So please I will appreciate you helping.
Here is my code, The script is successfully authorizing a user and picking the code to access his/her gmail account. Now I want to send the HTML email on behalf of that user.
require 'rubygems'
require 'google/api_client'
require 'launchy'
CLIENT_ID = 'my_app_Id_on_gmail_developers_console'
CLIENT_SECRET = 'the_secret_key'
OAUTH_SCOPE = 'https://mail.google.com/'
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Create a new API client & load the Google Drive API
client = Google::APIClient.new(:application_name => 'Ruby Gmail sample',
:application_version => '1.0.0')
gmail = client.discovered_api('gmail', "v1")
# Request authorization
client.authorization.client_id = CLIENT_ID
client.authorization.client_secret = CLIENT_SECRET
client.authorization.scope = OAUTH_SCOPE
client.authorization.redirect_uri = REDIRECT_URI
uri = client.authorization.authorization_uri
Launchy.open(uri)
# Exchange authorization code for access token
$stdout.write "Enter authorization code: "
client.authorization.code = gets.chomp
client.authorization.fetch_access_token!
#testing if it is working well by counting the emails.
#emails = client.execute(
api_method: gmail.users.messages.list,
parameters: {
userId: "me"},
headers: {'Content-Type' => 'application/json'}
)
count = #emails.data.messages.count
puts "you have #{count} emails "
# Pretty print the API result
jj #emails.data.messages
how can I do this? is there a way I can an external html file which is the email file to be sent. then I can sent this file using the script?
I partially accept the answer above since you can send an email through STMP pretty easily but with the gmail API it's even easier. According your code it should looks like this:
message = Mail.new
message.date = Time.now
message.subject = 'Supertramp'
message.body = "<p>Hi Alex, how's life?</p>"
message.content_type = 'text/html'
message.from = "Michal Macejko <michal#macejko.sk>"
message.to = 'supetramp#alex.com'
service = client.discovered_api('gmail', 'v1')
result = client.execute(
api_method: service.users.messages.to_h['gmail.users.messages.send'],
body_object: {
raw: Base64.urlsafe_encode64(message.to_s)
},
parameters: {
userId: 'michal#macejko.sk'
},
headers: { 'Content-Type' => 'application/json' }
)
response = JSON.parse(result.body)
For multi-part email with the attachment:
message = Mail.new
message.date = Time.now
message.subject = 'Supertramp'
message.from = "Michal Macejko <michal#macejko.sk>"
message.to = 'supetramp#alex.com'
message.part content_type: 'multipart/alternative' do |part|
part.html_part = Mail::Part.new(body: "<p>Hi Alex, how's life?</p>", content_type: 'text/html; charset=UTF-8')
part.text_part = Mail::Part.new(body: "Hi Alex, how's life?")
end
open('http://google.com/image.jpg') do |file|
message.attachments['image.jpg'] = file.read
end
Just my input. I was able to create a script that emailed html to multiple users in about 100 lines. Without using an api. You need to look into using smtp. It is very simple. You define a server for it to use and then you use it's "send_message" method. Here's a link to a good site! GOOD SITE
I can't post my whole code here for security reasons however this should get you started
class Email_Client
attr_accessor :message_contents, :subject
def initialize(sender_name, receiver_name, sender_email, receiver_email)
#sender_name = sender_name
#receiver_name = receiver_name
#sender_email = sender_email
#receiver_email = receiver_email
end
def send_html
message = <<MESSAGE
From: #{#sender_name} <#{#sender_email}>
To: #{#receiver_name} <#{#receiver_email}>
MIME-Version: 1.0
Content-type: text/html
Subject: #{subject}
#{message_contents}
MESSAGE
Net::SMTP.start('SeRvEr_HeRe') do |smtp|
smtp.send_message message,
#sender_email,
#receiver_email
end
end

Resources