Austin Story

Ruby, Rails and Javascript Blog

Powered by Genesis

Pundit and Rolify Testing with Rails

September 21, 2014 By Austin Story Leave a Comment

Just ran into an oddity that I didn’t expect (due to a false assumptions) when testing permissions and wanted to send it out to the world.

I have an app with two types of roles; :admin or :user. I am using Rolify in combination with Pundit to perform the role based authorization of REST actions.

I mixin a module containing general purpose authorization classes. I do it this way because permissions schemes tend to change alot and centralization makes it easier to change. You could easily just add these to your pundit policy classes.

[ruby]
def is_admin?
user.has_role?(:admin)
end

def is_user?
user.has_role?(:user)
end

def is_allowed?
user.has_role?(:user, record)
end
[/ruby]

Pretty straight-forward. An administrator has the role of :admin, a user has a role of :user and a :user is only allowed to access records that they are explicitly granted permission on.

My error was the assumption that user.has_role?(:user) would return true if a user had a role of :user explicitly set on any object in the system. In a pundit action it would look something like this.

[ruby]
def index?
is_admin? || is_user?
end
[/ruby]

The problem is that this was returning false unless someone had a :user role set in general, not on a specific instance of a record.

I think code clears this up further, here is the error.

[ruby]
#Assign the user role of :user on a specific object instance
User.first.add_role(:user, SomeObject.first)
User.first.has_role?(:user) #= false

#Assign the user a role of :user
User.first.add_role(:user)
User.first.has_role?(:user) #= true
[/ruby]

So i had to alter this to use see if the User had the role of :user on any object in the system.

[ruby]
#Old definition, broken
def is_user?
user.has_role?(:user)
end

#New definition, fixed!
def is_user?
SomeObject.find_roles(:user, user).any?
end
[/ruby]

The new is_user? returns true when the user has a role of :user on any SomeObject in the system. Which is exactly what we need.

Lesson learned, I assumed that the method worked a certain way and lost several hours of debugging in my unit tests. I normally will go straight to IRB when i run into anomalies but because i strongly help my assumption I didn’t.

Filed Under: Integrations, Minitest, Ruby, Ruby on Rails Tagged With: Pundit, Rails, Rolify, ruby on Rails

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

Exporting Data to CSV in Ruby on Rails

February 10, 2014 By Austin Story 2 Comments

So in our application we have a list of clients that our users are tracking (called trackers). One of our clients needed the ability to quickly export this data. In ruby this is super easy. We just add a few lines to our controller and model. In our controller, we already have an instance of their active trackers (@trackers_enabled )and it just grabs the trackers that are enabled.

[ruby]
trackers_controller.rb

respond_to do |format|
format.html
format.csv { send_data @trackers_enabled.to_csv}
end
[/ruby]

This allows us to export the data by just appending .csv to the url, so to access this we just add a link in the view. In the model we just add.

tracker.rb
[ruby]
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |row|
csv << row.attributes.values_at(*column_names)
end
end
end
[/ruby]

This is a quick solution and can be found in about 20 places around the internet, but it adds some unnecessary fields like created_at, updated_at and user_id to the csv.

To limit that data we just have to do some investigation on the column_names and see what type of data it returns in IRB.

In irb
[ruby]
Tracker.column_names
=> ["id", "user_id", "address", "first_name", "last_name", "enabled", "created_at", "updated_at"]
[/ruby]

So now we know that column names is just an array of the columns. To grab just the ones we are interested in we edit tracker.to_csv to have the columns we want or we could edit column_names to just specify the columns we want. I opted with the first because it won’t have any unintended consequences.

tracker.rb

[ruby]
def self.to_csv(options = {})
CSV.generate(options) do |csv|
columns = %w(first_name last_name age address description)
csv << columns
all.each do |row|
csv << row.attributes.values_at(*columns)
end
end
end
[/ruby]

Then in the view code you can add something like this if you are using bootstrap.

[ruby]
<div class="container-fluid padded">
<%= link_to "Export #{@trackers_enabled.count} Trackers to CSV", params.merge(:format => :csv), :class => "btn btn-green" %>
</div>
[/ruby]

Filed Under: Programming, Ruby, Ruby on Rails

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

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