Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Rails 4.2 truncate_words method

September 11, 2014 By Austin Story Leave a Comment

Rails 4.2 added a new feature called truncate words. It allows you to do things like this.

[ruby]"In a world where everything is awesome".truncate_words(3)
"In a world…"[/ruby]

I wanted to step through this method to look at a few things I found in the code. Here is the full code

[ruby]
def truncate_words(words_count, options = {})
sep = options[:separator] || /\s+/
sep = Regexp.escape(sep.to_s) unless Regexp === sep
if self =~ /\A((?:.+?#{sep}){#{words_count – 1}}.+?)#{sep}.*/m
$1 + (options[:omission] || ‘…’)
else
dup
end
end[/ruby]

The first thing that I noticed is that it recognizes two additional options
:separator allows you to change the thing that splits up words. For instance, you could do something like cut off the string at the third i. That would look like this.

[ruby]"Once i went to india and ate ice".truncate_words(3, {separator: ‘i’})
"Once i went to india and ate …"[/ruby]

There is also :omission, which allows you to add something besides … at the end of the truncation.

Now that we know the options, lets look at the code.

The first two lines setup the separator that is used to count the number of words. The first line either takes it from the options hash passed in or defaults it to a space. The second line converts the separator into regular expression language by escaping it (i.e. adding 1 or more \) UNLESS the separator is already of class Regexp. I suspect the unless is so that we don’t get double escaping that isn’t handled already in the Regexp library.

[ruby]sep = options[:separator] || /\s+/
sep = Regexp.escape(sep.to_s) unless Regexp === sep[/ruby]

Now that we have our separator Regex’ed out, we check the string for it’s match. Self is going to be some sort of string that responds to matching a regex. If it finds a match the truncate_words will return the match (which is stored in the $1 global variable) along with either the specified omission or ‘…’ at the end. If we don’t get enough matches, then the string is just duplicated out.

[ruby]
if self =~ /\A((?:.+?#{sep}){#{words_count – 1}}.+?)#{sep}.*/m
$1 + (options[:omission] || ‘…’)
else
dup
end
[/ruby]

Something I’m wondering about is why do they duplicate the string at the end if no match is found? Wouldn’t just sending out self work and not eat up a tiny bit more memory?

In my next post I analyze the regex that is used to do matching on this string.

Filed Under: Programming, Ruby on Rails Tagged With: Rails 4.2, ruby on Rails, Truncate_words

Thoughts on my first EmberJS project

September 5, 2014 By Austin Story Leave a Comment

Just cooked up an EmberJS project and wanted to share some thoughts on the framework as a whole and also throw some gotchas.

1. Many things work out of the box. However, when you need to do something that is not out of the box, you will find few resources to help. Worse yet, things change so much that found resources may not.

2. Some things are shockingly easy to do. Some of those things include data validations, 2 way binding and active record (rails) integration with active model serializer.

3. Some things are shockingly hard to do. For instance, looking over a javascript object is pretty simple in javascript or jQuery. However, in ember (with handlebars) you have to convert it into an ARRAY first, then it will loop pretty easily. This surprised me because EmberJS is javascript… looping over and displaying JSON should be pretty easy.

If I had one recommendation, it is to not use templating languages or extensions like emblem. I used this during my first project. It is similar to slim or haml and makes it super easy to see how the markup will be. But the downside is that whenever you need to do something unique, you will fight with it in order to get it implemented.

Javascript frameworks look like they will be the way of the future so good luck if you get started!

Filed Under: Javascript, Ruby, Ruby on Rails Tagged With: Emberjs, ruby, ruby on Rails

Adding Nested Image Attributes to Rails 4 App using Paperclip

February 27, 2014 By Austin Story 1 Comment

***Update – this no longer works due to changes in Paperclip but leaving here for historical context.  I have moved to using the gem Refile for image stuff***

So have a new web application where users will be able to upload images along with a post. I haven’t used the ruby gem Paperclip from ThoughtBot since rails 3.2 (which seems like it was only a couple months ago) so I thought I would write up a post on how I got it working.

The background of the app

  • Post have many images
  • Image is polymophic and can belong to either Post or Comment

So first step is to add the gem ‘paperclip’ to your gem file and then run bundle install.

Next, configure paperclip in development/production.rb   For this app we will be doing file storage locally until it is live

config/enviornments/development.rb

[code]
Paperclip.options[:command_path] = "/usr/local/bin"
[/code]

After that we need to setup our models for Image and Post. Image is polymorphically related to Post as imageable and also contains content through the paperclip gem. Post has images and can accept nested attributes for images.

app/models/image.rb

[code]
class Image < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
has_attached_file :content, :styles=>{:medium => "300×300>", :thumb => "100×100>"}
validates_attachment_content_type :content, :content_type => %w(image/jpeg image/jpg image/png)
end
[/code]

app/models/post.rb

[code]
class Post < ActiveRecord::Base
belongs_to :user
has_many :images, :as => :imageable, dependent: :destroy
accepts_nested_attributes_for :images
end
[/code]

Now that the models are good, we have to code around the strong parameters that were added in rails 4. Notice that in the private section we are adding ‘images_attributes: [:content]’ to prevent the image upload from being filtered and adding @post.images.build to the new action so that our view can render out the file tag properly.

app/controllers/posts_controller.rb

[code]
class PostsController < ApplicationController

def new
@post = Post.new
@post.images.build
end

def create
@post = Post.new(post_params)
@post.user_id = current_user.id

respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: ‘Post was successfully created.’ }
format.json { render action: ‘show’, status: :created, location: @post }
else
format.html { render action: ‘new’ }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end

private
#strong parameters
def post_params
params.require(:post).permit(:title, :description, images_attributes: [:content])
end
end
[/code]

Last part is the view, now that it is wired up it will just be adding a couple lines to our form. I removed the code that will spit out the errors that come through for succinctness here. Note that the upload image part has :images in fields_for which corresponds to our has_many :images in Post model and that the file_file :content corresponds to the has_attached_file :content in our Image mode.

Also, in order for the html field to accept images, make sure you add the multipart to the html.

app/views/posts/_form.html.erb

[code]
<%= form_for @post, :html => { :multipart => true } do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div>
Upload Image
<%= f.fields_for :images do |ph| %>
<%= ph.file_field :content %>
<% end%>
</div>

<div class="actions">
<%= f.submit %>
</div>
<% end %>

[/code]

That about does it. If you put this together and it doesn’t work, restart your server and it should start singing.

Filed Under: Programming, Ruby on Rails Tagged With: paperclip, Polymorphic, Rails 4, ruby on Rails, Strong Parameters

  • « Previous Page
  • 1
  • 2
  • 3
  • 4
  • Next Page »

Categories

  • AngularJS
  • Books
  • Devise
  • Elasticsearch
  • ES6
  • Information Security
  • Integrations
  • Javascript
  • Linux
  • Minitest
  • PhoneGap
  • Programming
  • React
  • Redux
  • Ruby
  • Ruby on Rails
  • Stripe
  • Testing
  • Theory
  • TypeScript
  • Uncategorized
  • Vue
  • Webpack