This article was originally published at Littlelines.
The release of Rails 4.1 this past week included some cool new features two of which are the introduction of enums and variants. Enums give us some syntatic sugar for handling attributes like status, role, etc. Variants allow us to handle separate types of templates from within a respond_to block on a given action. I setup a tiny Rails 4.1 application to demonstrate one possible use for these two new features.
Enum
This application has a basic user model with a name string and an email string. The users controller contains basic index and show actions to show a list to users and their respective details. In the user model, I included an enum attribute role to handle differentiating between users of different types (student, admin or staff). The basic way of defining an enum attribute is as follows:
1
enumrole:[:student,:admin,:staff]
However, with enums used in this fashion, order must always be maintained or you risk recasting your users with a new role unintentionally. Suppose, months later, a new developer comes along and adjusts the code above like so:
1
enumrole:[:golfer,:student,:admin,:staff]
We have now, inadvertanly, cast every user previously assigned with the role :student to :golfer. Oops.
For this reason I would most likely use explicitly defined enums to avoid any potential future mishaps:
1
enumrole:{student:0,admin:1,staff:2}
In this example, even if my new developer friend stumbles across this and updates it, they would have to explicitly overwrite the role associated with a given integer to cause any harm.
Once I have my enum defined, I now have access to all kinds of goodies to use throughout my application. I can now easily determine a given users role:
1
user.role# => "student"
I can easily determine if a user is a member of a particular role:
1
user.student?# => true
I can quickly assign/update a user’s role:
1
user.staff!# => [sql] true
Or see all of the users scoped to a particular role:
1
User.staff# => #<ActiveRecord::Relation []>
Variants
Variants can be used within a respond_to block to handle the same action in separate ways. Using the User model from above, we can render a show page unique for a particular user’s role.
In this example, the variants of the show action such as html.student will render a view template with the name matching: show.html+student.haml (or erb if you prefer). This allows us to use the same logic from our show action but render different content/layouts. This pattern could also be used to present different templates for mobile devices, webviews inside native mobile apps, etc.
With very little additional code, enums and variants allowed me to add a very basic role engine to my application and render content unique to a user’s role. These are just two of the fun new updates released in Rails 4.1. Check out the Release Notes for some additional reading.
This article was originally published at Littlelines.
My Approach
I love writing Ruby and I love using Rails. So when I started looking for a
client-side framework to help organize my front-end process and code, I was
cautious of frameworks that demanded I abandon my “Rails Way” and adopt their
process, style, and approach. I was looking for a framework that added value to
my “Rails App”, not a solution that wanted Rails to instead act as a
compliment to my client-side app.
Enter Angular stage left.
But wait, you say, tons of Angular apps use Rails (or any other framework) as
a backend api for their purely client-side application. Yes, you would be very
correct, however, unlike numerous other client-side frameworks, Angular allows
me to easily and quickly sprinkle it on top of my traditional Rails app if
that’s my preference.
CAVEAT - This article is only meant to demonstrate how I stayed a happy, healthy
Rails developer while still enjoying all the advantages Angular provides.
If, in your heart, you want nothing more than to make purely client-side apps
every day, then more power to you for being focused. Thanks for reading this
far - and please accept my token of thanks.
My happy-place with Angular and Rails is to let each framework do what it’s
good at and then move aside. For Rails, it is well suited to handle routing,
helpers and primary application logic. For Angular, it is best suited to
handle client-side interactions, dynamic bindings, ajax requests and
presentation logic. Using this approach I can stay away from so many headaches
caused by Angular routing, Rails remote linking and endless arbitrary jQuery
listeners.
Once I had settled on an approach to co-existence of Angular and Rails, my next
obstacle was the somewhat verbose and obscure Angular syntax.
CoffeeScript Sanity
Personally, I love using CoffeeScript (through that is in no way required to
enjoy Angular on Rails) and my first step in incorporating Angular into my
daily Rails flow was to get a handle on some of the more obtuse Angular syntax
in favor of the CoffeeScript class approach.
The first step was to create a base class (NGObject) to handle basic
dependency injection. This class iterates through the array of dependencies
passed via the class @$inject variable and creates an instance variable with
the same name. This gives us the ability to easily reference scope, services,
etc passed into our angular object by friendly means (@scope, @Thing,
@ThingSvc, etc). Once the dependencies are handled, the NGObject class will
check for an init() function and call it if one exists.
Next, I use that NGObject base class to build a variety of other classes to
handle specific angular object types such as NGController, NGService, etc.
Each of these classes exposes a register function that wires up our object to
the correct angular application. During object construction, we take the
attributes of a given object (controller, service) and apply them to the
proper scope. This allows us access to the attributes and functions of any
object in the view layer.
Specifically for service objects, we setup an NGService object that implements
event notifications allowing controllers, directives, etc to register callbacks
for specific service events. In the service, whenever desired, you can call the
notify function and inform all registered observers that the specific event
occurred.
We use an event_name for each event type which adds the ability to sanely
register and call multiple events explicitly as so:
1
handleEvent: ->notify'my:event'
1
MyService.on'my:event',->doStuff()
Included in my Rails projects, this helper allow me to write concise and
legible angular code in my preferred CoffeeScript class syntax. Here is a short
example of a rewritten Angular controller with the new syntax and format:
Is there anything explicitly problematic or wrong about the verbose
traditional Angular syntax? Absolutely not! Does this syntax make me a happier
developer and allow me to get my code out the door quicker? Without a doubt.
Setting up this syntax was a fun endeavor and my hope is it makes at least one
other developer’s life happier!
Rails Resource To The Rescue
One of the last remaining hurdles to quick and easy angular development with
rails is wiring up Rails resources with Angular. One source of frustration is
Angular’s handling (or lack thereof) of nested resource parameters. Here are a few
recent GitHub issues as examples of that frustration fix(ngResource): Add support for nested params
and Query params not serializes as expected.
Thankfully, Angular uses a modular approach to resource handling, so swapping
ngResource with a different library is a breeze.
After months of massaging the flat params from Angular in my Rails controllers, I
stumbled across Rails Resource.
Rails Resource is a promise based resource module that handles Angular resources
exactly as a default Rails application would expect. With very little code, we
can wire up Angular with our Rails resource and be on our way.
As an example, I have a basic Rails app with a model Beer that belongs_to a
Brewery. To wire up Angular with these resources using Rails Resource I could
write an Angular factory such as:
This code creates an Angular resource ‘Beer’ and maps it to the appropriate
endpoints in our Rails application. Our next step is to setup the association
with the Brewery model. You can see this done above with the following lines:
The serializer in Rails Resource looks to be quite powerful in allowing you to
both specify relationships and alter the json coming and going to resource
endpoints. The factory we have created above sets up a Beer resource in Angular
that accepts_nested_attributes_for a Brewery resource. With only the code
demonstrated above, the parameters sent to the logs on a create action (for example)
are just what Rails expects and is handled easily by a traditional Rails
create action.
1234
StartedPOST"/beers"for127.0.0.1ProcessingbyBeersController#create as JSONParameters:{"beer"=>{"name"=>"Goose Island IPA","description"=>"Hoppy Goodness","brewery_attributes"=>{"name"=>"Goose Island"}}}
The Result
During this article I have described three tools I use to make me a happier Rails
developer leveraging the power of AngularJS in my applications:
Letting each framework handle what it’s good at
The CoffeeScript helper that allows me to write more concise code in a syntax I enjoy
A resource module that wires up Rails resources with ease
Using these methods I setup a very basic CRUD Rails application on Github
davidstump/beers. With the exception
of the factory shown above, the only Javascript required was a short and sweet
Angular controller:
This style of Angular fits seamlessly into my familiar mental
model formed from my time developing Rails applications and ultimately makes
me a quicker, happier and healthier developer.
I would love any and all feedback (and Pull Requests) on both these approaches
as well as the NGHelper library itself. Thank you for taking the time to read
through my thoughts and happy coding!
This article was originally published at Littlelines.
I am an avid fan of simple, clean and elegant CoffeeScript (and thus JavaScript of course).
On top of your code being more approachable, I love the sense of accomplishment when
I find a clean way to solve a problem without immediately jumping to an external
library or plugin. Thus, when I was faced with the problem of handling touch
events on handheld and tablet devices for our new site, I started with a
blank page in my favorite editor.
Touch.coffee is a simple and straightforward CoffeeScript class written
with pure JavaScript that emits touch events to your application. The only
dependency this class utilizes is EventEmitter
to aid in handling the event triggers. The full source for this class is available
for browsing on GitHub
To get our class started, we will setup a few variables that will help us along the way.
The sensitivity variables allow us to specify how long a touch event should last before
we go ahead and emit our event to the rest of the application. This helps us differentiate
between a swipe style gesture versus a simple tap. The next two variables will help us gauge the
distance travelled during our touch event. Finally, the last two will let us store the
starting point of our event.
First we want to add a bind method to our class to attach the appropriate touch events to
whichever DOM element (or elements) specified. This method handles one or more elements
and attaches the touchstart, touchmove and touchend events and delegates the appropriate
handler methods for each type.
Once we have the events attached to the correct elements, we need to tell our class how to
handle the various event types along the way. Here we store our initial values once the touch
event is initially registered.
Next we need a method fired during the portion of the touch event where our finger is moving
across the screen. During this event we want to detect if another touch event is registered
and reset our listeners to avoid complications. We also want to update our two variables
tasked with telling us the distance our touch event has travelled.
Once a touchend event is triggered and the gesture is complete, we need to gather the total
distance travelled both horizontally and vertically. Once we have these values, we can use our
sensitivity variables to determine if the distance of the event is great enough to warrant emitting
to the rest of our application. We can also use the positive or negative value of
our difference/distance variable to indicate the specific direction of our event and emit the
correct notification.
Finally, once we have successfully registered a touch event and determined that it passes
our sensitivity threshold set initially, we need to emit the correct event to our application.
Using EventEmitter we can easily send out the proper
event notification with very little code.
With our new touch class, we can now bind touch events to any elements in our application.
1
Touch.binddocument.getElementById('menu')
Once we have our bindings set, performing actions based our touch events is as easy as calling
a method when a touch event is detected.
1
Touch.on'swipe:left',=>@toggleMenu()
While this class certainly doesn’t handle every possible interaction on a handheld or tablet
device, it does provide you with a great base for handling basic touch events throughout your
application with very little code. I welcome and look forward to any and all feedback, suggestions
and improvements and hope this little class proves helpful!
The mytime gem uses your git commit history, in the same manner as the timesheet alias did, to pull a log of your daily activities. Once you have this daily history, you can tell mytime to ‘push’ all of your commits as a timesheet log to Freshbooks using their API. Additionally, you can ‘submit’ custom timesheet entries to Freshbooks as needed.
MyTime Documentation
Use your git commit history to track your time. Uses Freshbooks API.
Installation
Add this line to your application’s Gemfile:
gem 'mytime'
And then execute:
$ bundle
Or install it yourself as:
$ gem install mytime
Usage
To link to your Freshbooks account (you will need your Freshbooks username and API token):
$ mytime setup
To initialize mytime in a project directory:
$ mytime init
To see project details:
$ mytime project
To list log:
$ mytime status
To submit custom time entry:
$ mytime commit [hrs] [custom_message]
$ mytime commit 1.5 "Add an additional note if desired"
To push your git logs from today for a given project:
$ mytime push [hrs]
$ mytime push 4.5
I would love some feedback and/or pull requests to extend this little gem to include other timesheets, features, etc. I made this to help myself keep track of my daily commits per project, but hopefully it helps out a few others along the way. Thanks for reading!
While I love coding with my editor in fullscreen mode, I also enjoy having apps such as Campfire or Rdio accessible on another monitor. One complaint I have had with the default OSX fullscreen mode is that it causes a second monitor to show nothing but the grey textured spaced background. I was thrilled the other day when I discovered a feature in Sublime that allowed me to use a “simple” fullscreen mode which behaves differently than the standard OSX mode. If you add the following to your Sublime preferences:
"use_simple_full_screen": true
Using the Enter Full Screen shortcut will allow you to have nothing but your code on one monitor and still use your second monitor for whatever apps your heart desires. Simple preference edit that has made my work flow that much better.
At the end of each day, I find myself crawling through the git logs to record my activities for the day on our timesheet software. It eventually occurred to me that with a few super simple arguments passed to the git log command, I could have a basic output of my timesheet for that day.
david:~/Projects/octopress❮source❯$ timesheet
2a08dac Adjust navigation mobile styles and hide search field
816cfef Apply custom style to site
b96240c Add Murky-Mussels Theme
Nothing complicated at all, but hopefully someone else finds this as helpful as I did. Thanks to @chris_mccord for adding the user.name snippet to this alias.
It’s not quite New Year’s Eve, however, I thought I would get a jump start on a resolution early this year. The resolution idea comes from my awesome co-workers at Littlelines who each mentioned re-starting their blog presence and making an effort to write and share more in 2013. I love the developer community [specifically the Ruby/Rails community as of late] and the ease/effort with which help, advice, problems and solutions are shared and discussed. For this new year, I am planning to make a concerted effort to write, share and help the community that has helped in uncountable ways getting me where I am today [which is a pretty fantastic happy place!].
Perhaps this sentimental resolution is partially a result of a bit too much holiday cheer [by way of food, presents, family and one midwest blizzard], but a little more cheer throughout the non-holiday months couldn’t hurt anyone, right?
With that, I hope everyone had a relaxing holiday break and is pumped to start a brand new 2013 in a few days. Also, keep and eye out for some exciting Dayton Ruby Community news in the near future!!