theKindOfMe

January 26, 2012

Rails Assets Pipeline Survival Guide

Filed under: Uncategorized — Tags: , , , , — yasi8h @ 1:50 am

Helpful settings

If you have assets pipeline enabled. By default you need to precompile your assets every time you change something (in production env). Having everything precompiled is cool but this will ask rails compile any assets that are not already compiled.

# Don't fallback to assets pipeline if a precompiled asset is missed
 config.assets.compile = true

Page Specific JS/CSS

If you want some JS/CSS to only be included in a specific set of pages.

  • break the page specific JS/CSS code to different files (ex:- profiles.js)
  • make sure they are not referenced in your manifest file (application.js)
  • add the following code snippets to the necessary files
application.html.erb (your main template)
<head>
 <title>FamousApp</title>
 <%= stylesheet_link_tag "application" %>
 <%= javascript_include_tag "application" %>
 <%= yield :head %>
 <%= csrf_meta_tags %>
</head>
specific_page.html.erb (the template where you want your JS to appear)
<% content_for :head do %>
 <%= javascript_include_tag "profiles" %>
<% end %>

production.rb

# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
 config.assets.precompile += %w( profiles.js )

Deploying with Capistrano

This is easy enough

load 'deploy/assets'

If you ever run across this problem:

# Disable warning message about missing dirs 'public/[javascripts|images|stylesheets]'
# src: https://github.com/capistrano/capistrano/issues/79
set :normalize_asset_timestamps, false
Advertisements

January 17, 2012

Note: Test and View available Rails Routes

Filed under: Uncategorized — Tags: , , — yasi8h @ 3:39 am

See all available routes

rake routes

Check route/path/URL helpers (in rails console)

app.the_route_you_want_to_test_path

OR

app.the_route_you_want_to_test_url

February 14, 2011

Fixing: /irb/completion.rb:9:in `require’: no such file to load — readline (LoadError) on rvm

Filed under: Uncategorized — Tags: , , , , , — yasi8h @ 10:25 am

Got this error to in one of the staging servers:

$ rails c production

/home/jooolaesa/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/irb/completion.rb:9:in `require’: no such file to load — readline (LoadError)
from /home/jooolaesa/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/irb/completion.rb:9:in `’
from /home/jooolaesa/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.0/lib/rails/commands/console.rb:3:in `require’
from /home/jooolaesa/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.0/lib/rails/commands/console.rb:3:in `’
from /home/jooolaesa/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.0/lib/rails/commands.rb:20:in `require’
from /home/jooolaesa/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.0/lib/rails/commands.rb:20:in `’
from script/rails:6:in `require’
from script/rails:6:in `’

It will appear if your ruby installation is not compiled with readline library. The solution is to recompile it with readline. If you are using RVM to manage your ruby installations you would go about doing it like this.

rvm package install readline

rvm remove 1.9.2 # note that 1.9.2 must be replaced with whatever ruby installation that you are going to recompile with readline support

rvm install 1.9.2 –with-readline-dir=$rvm_path/usr

Thats it!

Sources:

http://rbjl.net/20-rubybuntu-2-troubleshooting-common-ruby-ubuntu-problems
http://rvm.beginrescueend.com/packages/readline/

November 19, 2010

Rails Authorization wiht CanCan

Filed under: Uncategorized — Tags: , , — yasi8h @ 5:59 am

Intro

There are many authentication frameworks for rails. And a lot of people do use for getting basic authentication working in their apps. However most people tend to implement their own thing when it comes to authorization. I think this is because most people feel that their authorization needs are pretty simple and hence need no plugins. But when an application grows these home cooked solution may not scale well. After all why reinvent the wheel? (well i am sure that there is a time and a place where reinventing wheel is appropriate).

CanCan is a authorization framework that aims to be simple and provide you a central place to manage all your authentication logic. There are however more complex authorization frameworks out there. So if you do feel that CanCan doesn’t give you all the control you need you can do some googling.

You can get CanCan from https://github.com/ryanb/cancan.

Defining Authorization Logic

What i like the most about CanCan is its ability to define all the authentication logic in one single class. This is called Ability.

The following is an example from ASCII Casts episode 192 about CanCan. (Yes there are some railscasts and some asciicasts about CanCan).

class Ability
include CanCan::Ability

def initialize(user)
can :read, :all
end
end

A bit more complicated example from one of the projects that i am working on right now looks like this.

class Ability
include CanCan::Ability

def initialize(user)
if user && user.role == ‘Admin’
can :manage, :all
elsif user && user.role == ‘Producer’
#can :read, :all

can [:index, :new, :create], User # can view existing users and add new users to the system

can [:show, :edit, :update, :destroy], User do |user_o| # can edit/destroy any users/producers who are associated to the current_producer’s publications
user.users_related_to_my_active_publications([“Producer”, “User”]).include? user_o
end

# Catch all block that authorize doing anything on the rest of the Classes
#can :manage, User
can :manage, Asset

elsif user && user.role == ‘User’
#can :read, :all
can :index, User #as the root controller of the application is set to UsersController we need to let every role into UsersController’s index action.
#however this does not mean everyone can see a list of users. Non admins will be redirected.
can [:show, :update], User do |user_o| #let users update and view their own profiles, but not others
user_o.id == user.id
end

# Catch all block that authorize doing anything on the rest of the Classes
can :manage, Asset
can :manage, Audio
else
can :read, :all
end
end
end

CanCan is mostly independent from any authentication framework that you may use. It is not tightly coupled with any specific frameworks. But it does depend on the controllers having a method called ‘current_user’. This method should give the currently logged in user. So when CanCan wants to authorize some action it will grab the output from current_user and pass it in to the initialize method of the ability class. Inside the initialize method you put your custom logic and tell CanCan what and what not a certain role can do. This is accomplished by using the can method. With the can method you can define access levels for user roles per models.

When you say can:read, Asset. It means that the user role concerned can access controller actions that allows reading Assets. For example listing all the assets or viewing a asset through the show action. So in any can :x, :y statement, the x tells cancan what actions should be allowed and the y tell cancan for what objects (Users, Books…etc) the x actions are allowed for.

The actions available are what you have in any scaffold generated restful controller. However for ease cancan have grouped some of them in to some ‘actions’.

def default_alias_actions
{
:read => [:index, :show],
:create => [:new],
:update => [:edit],
}
end

The above method is from cancan’s source code and it defines the default alias for actions. So if you pass in :read it would mean that you are authorizing the index and show actions. The :manage action would basically authorize all actions.

If you want to check for custom actions you could just use those instead of the standard rest actions. For more info look at (https://github.com/ryanb/cancan/wiki/custom-actions).

You can pass in conditions to the can statements as follows (from https://github.com/ryanb/cancan).

can :read, Project, :active => true, :user_id => user.id

The conditions passed in as a hash in the third argument are tested against the user object on which the authorization is performed on.

Or as a code block.

can [:show, :update], User do |user_o| #let users update and view their own profiles, but not others
user_o.id == user.id
end

I want to let user’s update their own profiles but not others. So i have added a small check for that inside little block that is passed in as a argument to the can method.

Now you know how to write some basic authorization rules. But before cancan can get to work. It need to be ‘plugged in’ to your controllers. So we have to call the method

load_and_authorize_resource

in any controller on which we want out authorization rules applied. This method call will basically add a before filter that invokes the authorization. Or else you can put the authorization logic in separate controller actions, like:

def show
@article = Article.find(params[:id])
authorize! :read, @article
end

The above code (from https://github.com/ryanb/cancan) would check for the given ‘abilities’ for the current_user and throw a exception if the current_user does not have needed authorization.

You can also check the authorization logic in a adhoc manner.

<% if can? :update, @issue %>
<%= link_to “Edit Issue”, edit_issue_path(@issue) %>
<% end %>

The above code would check whether the current user have the right to access the edit action of the articles controller.

Handling Authorization Exceptions

When a user tries to do something that s/he is not authorized to (and given that you are invoking the correct cancan methods to check for authorization) cancan will throw a cancan access denied exception. This generates a ugly error message. So you can handle this in way you want by catching it like the following code (from https://github.com/ryanb/cancan) demonstrates.

class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
flash[:alert] = exception.message
redirect_to root_url
end
end

Authorization when fetching ActiveRecord records

CanCan does support doing authorization when retrieving records, however this have some limitations. For more info look at http://wiki.github.com/ryanb/cancan/fetching-records.

Drawbacks / Shortcomings

CanCan is a neat little gem. However it have its pros and cons. As for the cons i feel that its more easily used with restful controllers and not so easily with none restful controllers. This is not to say that you can’t use it with non restful controllers. I think CanCan is better suited for instances where you have some straight forward authorization work. As i have mentioned earlier in the article cancan tries to be simple and not too overly complicated. So it doesn’t have a lot of fancy features. But it does what it promises to do, and its pretty neat at it!.

October 16, 2010

Task Scheduling with Cron, RVM and Rails

Filed under: Uncategorized — Tags: , , , — yasi8h @ 4:00 am

I wanted to do something every hour in my rails app. Basically a scheduled task. So i looked around and there were some plugins. But i choose to go with plain old cron. This should be a very straight forward task. However there are some pitfalls to be aware of. Specially if you are using RVM which depends on some environmental variables that are set on the shell. I created a bash script that is called from corn as scheduled. If you do the same be sure to make the script executable. chmod +x your_script.sh

my crontab -e looks like this

# m h dom mon dow command
#task1
0,30 05-07 * * * /home/foobar/script task1
0,10,20,30,40,50 08-18 * * * /home/foobar/script task1
0,30 19-21 * * * /home/foobar/script task1
#task2
0,30 19-21 * * * /home/foobar/script task2
#clean up the logs # once a week every saturday, at 00:00 (midnight)
0 0 * * 6 /home/foobar/script task3

for clean code get the gist

I have scheduled three tasks here. I am calling the same script with different arguments.

The script.

Note the source statement in the beginning. This loads RVM. And i am using the rails runner to call the methods i want to. These are located in some model classes within my rails app. Using the runner is just one option, but there are many you can use. Take look at here for more information on this topic.
If you are interested in using a gem to do the scheduling for you. Take a look at this.
After writing this i found some more post on the net that shows some what more elegant and better ways of doing the same thing. I think you should definitely give them a read.

September 19, 2010

Notes from my First Rails 3 App

Filed under: Uncategorized — Tags: , , — yasi8h @ 12:52 pm

I just got stated with rails 3. Got in to some “not too hard to solve but takes a bit of a time to figure out a fix” type of issues. This post is a account of the problems and the solutions/work arounds i applied.

Notes on installing/using Mysql2

undefined method `errno’ for #Mysql2::Error:0x00000100ff0c98

On running rake db:create if you get a error such as:

undefined method `errno' for #Mysql2::Error:0x00000100ff0c98

this is a bug. Use the latest version of mysql2 adapter by adding this line to your Gemfile

gem 'mysql2', :git => 'http://github.com/brianmario/mysql2.git'

then it should be fine.

ref: https://rails.lighthouseapp.com/projects/8994/tickets/5502-rake-dbcreate-problem-in-rails3-with-mysql2

“Can’t connect to local MySQL server through socket ‘/opt/local/var/run/mysql5/mysqld.sock’ (2)”

If you get “Can’t connect to local MySQL server through socket ‘/opt/local/var/run/mysql5/mysqld.sock’ (2)” execute: locate mysql.sock and use the result in place of “socket: /Applications/MAMP/tmp/mysql/mysql.sock” which was where mysql.sock was located in my mac

socket: /Applications/MAMP/tmp/mysql/mysql.sock

Notes on installing Paperclip

make sure you have imagemagick installed

Notes on Using rails-ckeditor with rails3

If you get a error such as

NameError (uninitialized constant Ckeditor::Utils):

Then you need to patch rails-ckeditor

as: http://github.com/mooktakim/rails-ckeditor/commit/262d6120ef18c77167c472e912d373a58a3f85ba

January 31, 2010

Notes on setting up devise (authentication solution for rails)

Filed under: Uncategorized — Tags: , , — yasi8h @ 4:38 pm

From Devise’s project page:

Devise is a flexible authentication solution for Rails based on Warden. It:

  • Is Rack based;
  • Is a complete MVC solution based on Rails engines;
  • Allows you to have multiple roles (or models/scopes) signed in at the same time;
  • Is based on a modularity concept: use just what you really need.

I was playing around with devise trying to get it set-up in my app, came through some configuration errors on my part, thought of noting them down for future reference.

NoMethodErrors and NameErrors

  • if you are getting NoMethodErrors for methods such as user_signed_in?, current_user, user_session, admin_signed_in? in your ActiveViews, check your routes.rb file for correct “map.devise_for :”  statements. If you have users and a admin in your system and Users and Admin models in your models. You should have something like this:
    map.devise_for :users, :admin
    
  • If you are getting NameErrors like “undefined local variable or method `edit_user_path' for #….” (could be for new_admin_session_path…etc anything to do with session path) Then check whether you have mapped your controllers correctly on your routes.rb. If you are having a UsersController and a AdminController your routes.rb can have some lines like:
    map.resource :user
    map.resources :admins
    

March 5, 2009

Rails ActiveRecord: Having Multiple Relationships within Two Models

Filed under: Uncategorized — Tags: , , , , — yasi8h @ 3:03 am

noob alert!: I am pretty new to RoR. so i might not be solving the problem with the best possible solution.

Scenario 1: many-to-many + one-to-many

Task: I have two models. Contact and ContactSource. a Contact belongs to a ContactSource. and a Contact can be synced with one or more ContactSource(s). i need to get the ContactSource(s) with whom a given Contact is synced ex:- Contact1.synced_with => [ContactSource1, ContactSource2…]

Solution:  for the first relationship(one-to-many) we can use belongs_to. and for second we can use has_many with :through

class Contact :contacts_synced_with_contact_sources

end

class ContactsSyncedWithContactSource < ActiveRecord::Base belongs_to :contact belongs_to :contact_source end [/sourcecode] In the above code we have no problem accessing the data relevant to the two relationships. because: Contact.contact_source would point to the Contact Source who owns the Contact while Contact.contact_sources would point to the ContactSources with whom the Contact is synced with. but look at the next problem.... Scenario 2: many-to-many + many-to-many Task: I have two models. Book and Student. a student can own many books, while a book(this does not refer to a individual copy of a book, but to all the copies of a book) can be owned by many students. and a student have a collection of books that he loves. Problem: here we have two many to many relationships within two business entities. if you try to solve this with has_many :through or has_and_belongs_to_many, you would run in to a problem. in the first problem you referred to the ContactSources by using the property accessor contact_sources. but here if you try using student1.books how would ActiveRecord know what to return?(book the student love or the books he own?). you could solve this problem by using the :source option(is that what you call these in ruby? :P) in has_many... it would like this... has_many :books_i_love, :source => “book”, :through => :student_love_books

you can give a custom property accessor name such as books_i_love but then you have to use the :source => “book” to let rails know about what model(s) you are trying to access.

if you do not use the :source => “book” you would get a very helpful error message like this

ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :books_i_love or :books_i_love in model StudentLoveBook. Try 'has_many :books_i_love, :through => :student_love_books, :source => '. Is it one of :student or :book?

source follows…

class Student “book”, :through => :student_love_books

has_many :student_own_books
has_many :books, :through => :student_own_books
end

class Book < ActiveRecord::Base end class StudentLoveBook < ActiveRecord::Base belongs_to :student belongs_to :book end class StudentLoveBook < ActiveRecord::Base belongs_to :student belongs_to :book end class CreateBooks < ActiveRecord::Migration def self.up create_table :books do |t| t.string :name t.timestamps end end def self.down drop_table :books end end class CreateStudents < ActiveRecord::Migration def self.up create_table :students do |t| t.string :name t.timestamps end end def self.down drop_table :students end end class CreateStudentOwnBooks < ActiveRecord::Migration def self.up create_table :student_own_books do |t| t.column :student_id, :integer t.column :book_id, :integer t.timestamps end end def self.down drop_table :student_own_books end end class CreateStudentOwnBooks < ActiveRecord::Migration def self.up create_table :student_own_books do |t| t.column :student_id, :integer t.column :book_id, :integer t.timestamps end end def self.down drop_table :student_own_books end end [/sourcecode] hope this would help someone/myself in the future 🙂

Create a free website or blog at WordPress.com.