Blog List

William

Sending mail with Mailgun and Faraday

Earlier I wrote a neat helper to send mail with Mailgun-ruby. It worked great locally but as soon as it went to OpenShift it failed, json was borked.

I could not figure it out so I decided to switch to Faraday, the method I found on OpenShifts blog.

Of course their example didn't fully work. Mailguns SSL was crap so I have to ignore that, and update to v3.

def self.send from, to, subject, body, tpl
  template = ERB.new File.new(tpl).read, nil, "%"
  html = template.result(binding)

  message_params = {:from    => from,
         :to      => to,
         :subject => subject,
         :html    => html}

   conn = Faraday.new('https://api.mailgun.net/v3', { ssl: { verify: false } }) do |faraday|
      faraday.request  :url_encoded
      faraday.response :logger
      faraday.adapter  Faraday.default_adapter
    end
       
    conn.basic_auth('api', $maingun_apikey)
    conn.post("#{$maingun_domain}/messages", message_params)
end

 Not ideal but it does the job.


William

Sending mail with Mailgun, Sinatra/Ruby and ERB

One of the next steps in the blog was to be able to send mail. I absolutly hate managing mail servers so any time I can use Mailgun I jump on it. The service is quite amazing and lets you do a lot more then just send mail.

I had to figure out how to render ERB views into variables. Then I had to install the mailgun-ruby gem and configure it with my settings.

I stuck to the two things together and got a simple mailer helper that uses a template to style the email. Certainly there are more things to be added here but it's a good start.

The helper:

 module Sinatra
module SimpleRubyBlog
module Helpers
module Mail
def self.send from, to, subject, body, tpl
template = ERB.new File.new(tpl).read, nil, "%"
html = template.result(binding)

message_params = {:from => from,
:to => to,
:subject => subject,
:html => html}

mg_client = Mailgun::Client.new $maingun_apikey
mg_client.send_message $maingun_domain, message_params
end
end
end
end
end

The ERB:

<html>
<head></head>
<body>
<h1>E-mail Test</h1>
<ul>
<li>To: <%= to %></li>
<li>From: <%= from %></li>
<li>Subject: <%= subject %></li>
<li>Body: <%= body %></li>
</ul>
</body>
</html>

Then I call it

 Mail.send('[email protected]', '[email protected]', 'Hi', 'This is cool', './views/emails/email.erb')

Pretty basic!

 

 



William

Ruby Cloudinary Uploading with SEO file names

I learned recently how important it is to keep things on the same domain (not sub) and to seo every possible thing, including image names.

In our case the free Cloudinary does not allow custom domains, but that's ok. I do control the file names for the images, so why not slugify them based on the title?

Here you can see what I did.

if !params['myfile'].nil?
   accepted_formats = [".jpg", ".png", ".gif"]
   halt 500 unless accepted_formats.include? File.extname(params['myfile'][:filename])

new_image = File.open('public/assests/images/' + params['myfile'][:filename], "wb") do |f| f.write(params['myfile'][:tempfile].read) end old_name = 'public/assests/images/' + params['myfile'][:filename] new_name = 'public/assests/images/' + params[:title].slugify + File.extname(params['myfile'][:filename]) File.rename(old_name, new_name) upload = Cloudinary::Uploader.upload(new_name, :use_filename => true) image = upload['secure_url'] File.delete(new_name) end

I've only been doing this for most of the week so I'm sure it could be better.


William

OpenShift Environment Variables with Ruby/Sinatra

I was searching for "openshift set environment variables" and I found serveral options like .openshift deploy files, rhc, export, etc. 

I have not setup rhc and since OpenShift made me use a crazy password I don't know my login, no worries, we have other options.

If you do have rhc setup, it's easy to set env variables:

 rhc set-env CLOUDINARY_CLOUD_NAME= CLOUDINARY_KEY=CLOUDINARY_SECRET=  -a r

But if you're like me and haven't installed it yet then this may work better, just create a user_var for your env var :D "..." being your setting.

echo -n .. > ~/.env/user_vars/CLOUDINARY_CLOUD_NAME
echo -n .. > ~/.env/user_vars/CLOUDINARY_KEY
echo -n .. > ~/.env/user_vars/CLOUDINARY_SECRET

That's all it'd take to set the vars to be used for the Sinatra Decent Blog.



William

TinyMCE Image File Uploads with Sinatra

I wanted to have the ability to insert images into posts and not have to use some 3rd party tool to do it.

Since we're already doing image hosting I figured it'd be a good idea to hook up TinyMCE.

I googled for "tinymce image upload ruby" and found a lot of rails examples. Nothing for Sinatra. 

Sinatra is a tad easier then Rails, loveley, so it was easy to get it working based on this example

app.post '/create/upload' do   halt 500 unless !params['image'].nil?
  image=nil
  new_image = File.open('public/assests/images/' + params['image'][:filename], "wb") do |f| 
f.write(params['image'][:tempfile].read) 
end
 
  "<script>top.$('.mce-btn.mce-open').parent().find('.mce-textbox').val('/images/#{image}').closest('.mce-window').find('.mce-primary').click();</script>"
end

Then in the html that loads TinyMCE

<iframe id="form_target" name="form_target" class="hidden"></iframe>
<form id="upload_form" action="/create/upload" target="form_target" method="post" enctype="multipart/form-data" class="hidden">
  <input name="image" type="file" onchange="$('#upload_form').submit();this.value='';">
</form>

Then your TinyMCE init

plugins: ['image'],
file_browser_callback:
function(field_name, url, type, win) {
if(type=='image') $('#my_form input').click();
},

It was really quite simple to adapt Rails to Sinatra and use the built in TinyMCE image plugin, saved a lot of time trying to add it outside the editor.

 


William

Sinatra, creating & using proper folder structure

Before I continue the Decent Sinatra Blog project I want to clean it all up and switch to a MVC style. It's mostly there, since it's hard to not want to follow MVC, but Sinatra - and the examples I used - did not really follow it. 

I kept looking at Rails examples and enjoyed looking at the MVC structure and felt at home. But I was told to pickup Sinatra and well that's what I did, might as well stick with it.

Googling around for "sinatra folder structure" I found a few good articles.

One git repo called sinatra-template had a decent setup going, it even includes some files but I want the app folder and some other things. 

I also found this article that talks about things in a bit more details. 

It looks like I'll have so me home work to do before tomorros project, refactoring to a complete MVC and getting ready to roll out even more features.


William

Sinatra Decent Blog: Comments system added.

Sinatra Decent Blog: Comments system added.

What blog would be complete without comments.

Sure there are a lot of options when it comes to adding comments. Many people would just use some 3rd party tool to say inject facebook into your page, that's awesome - but slow. 

I don't want to bloat out this simple blog example so a built in comment system is a must. Luckily DataMapper provided a decent base example. It'd be nice to abstract it more, allowing for nested commenting, but that's a bit advanced for my goals today.

I'm not a designer so googling around I found a decent looking comments display. I needed to add gravatar to the comments and that lead me to needing to md5 the posters e-mail address.

<%= Digest::MD5.hexdigest(comment.email) %>

I couldn't find a decent Bootstrap Comment Form so I built my own

<form method="post" action="/comment/<%= post.slug %>">  
<div class="row">
    <div class="col-md-6">
      <div class="form-group">
        <input name="name" type="text" class="form-control" placeholder="Your Name" required>      </div>
    </div>
    <div class="col-md-6"> 
    <div class="form-group"> 
      <input name="email" type="email" class="form-control" placeholder="Your e-mail" required>      </div> 
</div>
  </div>
  <div class="form-group">
<textarea name="body" placeholder="Comments" class="form-control" required></textarea>
  </div>
  <div class="form-group"> 
  <input name="website" type="text" class="spam-control">
  </div>
  <button class="btn btn-block btn-primary">Post my comment</button>
</form>
 

A little more work and it'd be better, just a 5min form to get going. I added a honey-pot hidden token to try and stop spam.

The rest was quite simple following the rest of the code I already have. Since I'm replicating some stuff and trying to get templates to include better it looks like some refactoring is in order.