Skip to content

Instantly share code, notes, and snippets.

@john-patrik
Created April 8, 2012 14:35
Show Gist options
  • Save john-patrik/2337618 to your computer and use it in GitHub Desktop.
Save john-patrik/2337618 to your computer and use it in GitHub Desktop.
Rails Core

Active Admin

http://activeadmin.info/documentation.html

Note that I usually use Devise to authenticate the Active Admin user (which by default is AdminUser), so check that part the gist out first!

Resources

https://github.com/gregbell/active_admin/wiki/How-to-add-User-Accounts-for-users-to-administer-their-personal-accounts

Installation

First add the gems.

# Gemfile
gem 'activeadmin'
gem 'sass-rails'
gem 'meta_search', '>= 1.1.0.pre'

Install gems.

$ bundle

Run the installer.

$ rails generate active_admin:install

Migrate the database.

$ rake db:migrate

Configuration

Email settings for production.

# config/environments/production.rb
config.action_mailer.default_url_options = { :host => '<your host>' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :address  => 'smtp.gmail.com',
  :port     => 587,
  :domain   => '<your domain>',
  :user_name => '<username>',
  :password => '<password>',
  :authentication => 'plain',
  :enable_starttls_auto => true
}

Email settings for development.

# config/environments/development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
config.action_mailer.delivery_method = :test

Make sure that the necessary resources are precompiled.

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

config.assets.compile = false

By default (with a default Rails project)

Log in to your new admin interface at /admin

username: admin@example.com
password: password

Active Admin resources

To add your resource to active admin, register them like so.

rails generate active_admin:resource [MyModelName]

Devise can then handle permissions by supplied authentication methods to use in the resouce controller. Like so.

# [model]_controller.rb
class [Model]Controller < ApplicationController
  before_filter :authenticate_user!, :except => [:index, :show]
end

AdminUser configuration

https://github.com/gregbell/active_admin/wiki/Your-First-Admin-Resource%3A-AdminUser

First add the admin model, by standard AdminUser, as a resouce.

rails generate active_admin:resource AdminUser

Simplify the creation of new administrators. Just enter their email and the password gets sent to them.

# app/admin/admin_users.rb
ActiveAdmin.register AdminUser do
  #...
  form do |f|
    f.inputs "Admin Details" do
      f.input :email
    end
    f.buttons
  end
end

Send a recovery password upon AdminUser creation, and when creating setting of password is optional.

# app/models/admin_user.rb
after_create { |admin| admin.send_reset_password_instructions }
def password_required?
  new_record? ? false : super
end

To stop from deleting the last AdminUser from the system, add this.

before_destroy :raise_if_last
def raise_if_last
  if AdminUser.count < 2
    raise "Can't delete last admin user"
  end
end

Interface

Resource interface example.

ActiveAdmin.register User do
  form do |f|
    f.inputs "Details" do
      f.input :email
      f.input :role, :as => :select, :multiple => false, :required => true, :collection => User::ROLES
    end
    f.buttons
  end
  
  index do
    column :id
    column :email
    column :role
    column "Joined", :created_at
    column :last_sign_in_at
    default_actions
  end
end

ActiveAdmin & CanCan

https://github.com/gregbell/active_admin/wiki/How-to-work-with-cancan

Testing

Authentication with Devise and CanCan

Active Admin?

Devise Installation

Gemfile.

gem 'devise'

Install.

$ rails generate devise:install

Tell Devise to authenticate AdminUser (the default ActiveAdmin admin user).

$ rails generate devise AdminUser

Devise also requires this config setting.

# development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }

Devise

Roles

https://github.com/plataformatec/devise/wiki/How-To:-Add-a-default-role-to-a-User

https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-Role

CanCan

https://github.com/ryanb/cancan/

https://github.com/ryanb/cancan/wiki/_pages

https://github.com/ryanb/cancan/wiki/Controller-Authorization-Example

https://github.com/ryanb/cancan/wiki/Role-Based-Authorization

Active Admin

https://github.com/gregbell/active_admin/wiki/How-to-add-User-Accounts-for-users-to-administer-their-personal-accounts

Application.html.erb

<!-- Meta -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="" />
  <meta name="author" content="CDLF International" />

  <%= javascript_include_tag params[:controller] %>
  <%= stylesheet_link_tag params[:controller] %>

Carrierwave image uploader example

# encoding: utf-8

class InspirationImageUploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  process :convert => 'png'
  def filename
    super.chomp(File.extname(super)) + '.png' if original_filename
  end

  process :resize_to_fill => [700, 437]
  process :interlace

  version :thumb do
    process :resize_to_fill => [240, 150]
  end

  def interlace
    manipulate! do |img|
      img.format('png')
      img.interlace('PNG')
      img
    end
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_white_list
    %w(jpg jpeg gif png)
  end

end

Facebook connections

Check out the Graph API Explorer here: developers.facebook.com/tools/explorer

Definitions

  • Canvas app: Kind of like embedded websites (like heroku apps)
  • FB Page: Facebook Fanpages
  • FB Tab: Facebook kind of apps or sub-pages within FB Pages

Page

To read a Page you need either one of these

  • An Application Access Token
  • A User Access Token

If the Page is restricted in any way, the user needs to have the right permissions (which can be read via the User Access Token).

Access Tokens

User Access Token

  • When accessing a Page with a user access token, the content of the page depends on the permissions of the user, or if no user is logged in (no fb session), whatever page content is public.

Page Access Token

https://developers.facebook.com/docs/reference/api/page/#page_access_tokens

If you have 'manage_pages' permission on a Page, you can retrieve (see below) a Page Access Token to that particular Page.

If you use that Page Access Token instead of your User Access Token, you will be able to act as the Page - meaning that you can manage/administer that Page.

Retrieving Page Access Token

First make sure you have 'manage_pages' permission on your current User Access Token.

  • Retrieve all Tokens you can HTTP GET /USER_ID/accounts

  • Retrieve one specific Token

HTTP GET /PAGE_ID?fields=access_token

Tips & Tricks

Add Facebook Application to a Page:

<script>
        top.location = 'http://www.facebook.com/add.php?api_key=YOUR_APP_ID&pages=1';
</script>
source 'https://rubygems.org'
ruby '1.9.3'
gem 'rails', '3.2.11'
gem 'thin'
gem 'jquery-rails'
gem 'active_link_to'
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
group :development, :test do
gem 'sqlite3'
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'guard-rspec'
gem 'rb-fsevent'
end
group :test do
gem 'capybara'
gem 'faker'
gem 'database_cleaner'
gem 'launchy'
end
group :production do
gem 'pg'
end

Heroku

http://railsapps.github.com/rails-heroku-tutorial.html

https://devcenter.heroku.com/articles/rails3x-asset-pipeline-cedar/

Setup Heroku

Sign up if you haven't already: https://api.heroku.com/signup

Install the toolbelt: https://toolbelt.heroku.com/

Setup the toolbelt.

$ heroku login

Setup the app

Install the heroku gem.

$ gem install heroku

Create the Heroku app (assumes you have an account already).

$ heroku create [heroku-test] --stack cedar

Configure the project

Only have the sqlite3 gem in development and test environments.

# Gemfile

group :development, :test do
  gem 'sqlite3'
end
group :production do
  gem 'pg'
end

Also, use thin as the webserver instead of webrick.

# Gemfile

group :production do
  gem 'thin'
end

Heroku and the Rails asset pipeline

Heroku works best when assets are deployed precompiled. This also has the added benefit of reducing dyno load.

# config/application.rb
# Heroku requires this to be false
config.assets.initialize_on_precompile = false

To precompile assets before deployment to Heroku.

$ RAILS_ENV=production bundle exec rake assets:precompile

Don't forget to add your fresh precompiled assets.

$ git add public/assets
$ git commit -m "precompiled assets"

Deploying the app

Push your project to Heroku.

$ git push heroku master

DNS

https://devcenter.heroku.com/articles/custom-domains

First tell heroku to handle requests for the given url.

$ heroku domains:add [URL] --app [AppName]

Then configure your DNS to point your url to the heroku app url, with a CNAME;

Example: codeleaf.com => codeleaf.herokuapp.com

Useful command line tools (unix).

$ dig ns codeleaf.net
$ host codeleaf.net
$ whois codeleaf.net

Caching

https://devcenter.heroku.com/articles/rack-cache-memcached-static-assets-rails31

Other

Don't use the gem 'therubyracer' - it uses a large amount of memory.

When creating a resource

The following things are generally included when creating a resource.

  • Accessors
  • Validations
  • Associations
  • Utility methods
    • to_s
    • display_name

Associations

belongs_to :associated_model
has_many :other_associated_models, :dependent => :destroy

Accessors

# Accessor attributes (get)
attr_accessor :attr1, :attr2

# Accessible attributes (set)
attr_accessible :attr1, :attr3, :associated_model_id

Validations

# Validate attributes
validate :attr1, :presence => true

# Validate associated models
validate :associated_model, :presence => true
validates_associated :associated_model

# Custom validation methods
validates :has_cat
def has_cat
  unless self.cat
    errors.add(:cat, "Must have a cat!")
  end
end

Utility methods

def to_s
  return self.attr1
end

# ActiveAdmin wants this.
def display_name
  self.to_s
end

RVM

The ruby version manager.

https://rvm.io

Installation

$ curl -L https://get.rvm.io | bash -s stable

Installing ruby on OSX Lion

Need this.

  • XCode command line tools from AppStore.
  • Homebrew - Homebrew-dupes & apple-gcc4.2
  • RVM

Install XCode command line tools from AppStore. Apple took osx-gcc-installer from Github and put that into XCode.

Install Homebrew and use the to install gcc-4.2 from the homebrew-dupes repository.

$ brew tap homebrew/dupes
$ brew install apple-gcc42

Then it's time to use RVM to install a ruby version, by using the new compilator.

$ CC=gcc-4.2 rvm install 1.9.2

Updating RVM

$ rvm get stable

Upgrading rubies

$ rvm upgrade [old ruby version] [new ruby version]

Or.

$ rvm upgrade [new ruby version]

Copying gemsets to new ruby

$ rvm gemset copy [old_ruby@gemset] [new_ruby@gemset]

Use a specific ruby version

Set ruby version via RVM and install rails.

$ rvm use 1.9.2
$ gem install rails

Start the project.

$ rails new heroku-test
$ cd heroku-test

Create and reload the environment.

$ rvm --create --rvmrc use 1.9.2@heroku-test
$ bundle install

Rails

Install via RVM

See 'rvm.md' for how to install a ruby version.

Then set ruby version via RVM and install rails.

$ rvm use 1.9.3
$ gem install rails

Start the project.

$ rails new heroku-test
$ cd heroku-test

Create and reload the environment.

$ rvm --create --rvmrc use 1.9.3@heroku-test

Then git the .rvmrc file.

$ git add .rvmrc
$ git commit -m "Added rvmrc to the project"

Gems

Remove this.

# Gemfile
gem 'sqlite3'

Add this.

# Gemfile
group :test do
  gem 'sqlite3'
end

group :production do
  gem 'thin'
  gem 'pg'
end

group :development do
  gem 'sqlite3'
end

Finally install the gems.

bundle install

Git

Make git ignore stuff.

# .gitignore

# Editors
\*.swp

# Rails
*.rbc
*.sassc
.sass-cache
capybara-*.html
.rspec
/.bundle
/vendor/bundle
/log/*
/tmp/*
/db/*.sqlite3
/public/system/*
/coverage/
/spec/tmp/*
**.orig
rerun.txt
pickle-email-*.html

Git the project.

git init    
git add .
git commit -am "Initial commit."

TODO: Rails asset pipeline

http://guides.rubyonrails.org/asset_pipeline.html

SublimeText 2

Settings

User Settings

{
  "auto_complete": false,
  "color_scheme": "Packages/User/Railscasts.tmTheme",
  "detect_indentation": false,
  "font_size": 12.0,
  "scroll_past_end": false,
  "tab_size": 2,
  "translate_tabs_to_spaces": true,
  "trim_trailing_white_space_on_save": true,
  "use_tab_stops": true,
  "word_wrap": false,
  "detect_slow_plugins": false
}

Macros & Keybinds

User Keybinds

[
  {
    "args":
    {
      "contents": "%$0 %>"
    },
    "command": "insert_snippet",
    "context":
    [
      {
         "key": "selector",
         "match_all": true,
         "operator": "equal",
         "operand": "source.ruby, source.erb, text.html.ruby, text.haml, source.yaml, source.css, source.scss, source.js, source.coffee"
      },
      {
        "key": "preceding_text",
        "operator": "regex_match",
        "operand": ".*<",
        "match_all": true
      }
    ],
    "keys": [ "%" ]
  },
  { "keys": ["super+shift+right"], "command": "indent" },
  { "keys": ["super+shift+left"], "command": "unindent" },
  { "keys": ["shift+alt+a"], "command": "move_to", "args": {"to": "bol", "extend": true} },
  { "keys": ["shift+alt+l"], "command": "move_to", "args": {"to": "eol", "extend": true} }
]

Testing

RSpec API: http://rubydoc.info/gems/rspec-rails/frames

https://github.com/plataformatec/devise

http://ruby.railstutorial.org/chapters/static-pages#sec:first_tests

http://guides.rubyonrails.org/testing.html

Railscasts: http://railscasts.com/episodes/275-how-i-test

Kudos to Gary Rafferty for providing this: http://garyrafferty.com/2011/09/29/Testing-devise-with-rspec-and-capybara.html

DatabaseCleaner: https://github.com/bmabey/database_cleaner/

FactoryGirl: https://github.com/thoughtbot/factory_girl/wiki/Usage

Test-Driven Development (TDD)

The Red-Green-Refactor mindset is used to improve the flow of programming, making it more enjoyable, focused and productive.

TDD often also results in the code being more elegant and simple.

But, it's not always the right choice. (Nothing ever is)

Setup

Add the required gems to the project, to both the test and the development environment.

# Gemfile

group :development, :test do
  gem 'sqlite3'
  gem 'rspec-rails'
  gem 'factory_girl_rails'
  gem 'guard-rspec'
  gem 'rb-fsevent'
end

group :test do
  gem 'capybara'
  gem 'faker'
  gem 'database_cleaner'
  gem 'launchy'
end

Configure mailer.

# config/environments/test.rb

config.action_mailer.default_url_options = { :host => "localhost:3000" }

Install.

$ bundle

Initialize rspec.

$ rails generate rspec:install

Initialize and load the current schema into the test database.

$ rake db:test:load

Subsequently, load the current schema into the test database like so.

$ rake db:test:prepare

Add support for capybara to rspec.

# spec/spec_helper.rb

require 'capybara/rspec'

You may also want to delete these lines from the same file.

# spec/spec_helper.rb

# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"

Configure output of rspec.

# .rspec

--format documentation

Configure rails test generators.

# config/application.rb

class Application ...
  config.generators do |g|
    g.test_framework :rspec,
      fixtures: true,
      view_specs: false,
      helper_specs: false,
      routing_specs: false,
      controller_specs: true,
      request_specs: true
    g.fixture_replacement :factory_girl, dir: "spec/factories"
  end

Delete your default test/ directory, since we're using spec/ instead.

$ rm -r test

FactoryGirl

https://github.com/thoughtbot/factory_girl/wiki/Usage

Add this.

# spec/spec_helper.rb

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

Writing tests

Now you can start writing your test stubs.

# spec/requests/pages_spec.rb
require 'spec_helper'

describe "Pages" do

  describe "GET /" do
    it "should be a success"
    
    it "should have the title 'Welcome'"
    
    it "should have a login link"
  end
end

Try running rspec with just the stubs, as rspec documentation.

$ rspec --format doc

Integration test

Integration tests are "black box" tests and are meant to test the system functionality from an external perspective.

Integration tests are also known as Request Specs in the context of RSpec.

A sample spec, with capybara DSL (domain specific language).

# spec/requests/pages_spec.rb
require 'spec_helper'

describe "Pages" do

  describe "Home" do
    it "should have the content 'Home Page'" do
      visit '/home'
      page.should have_content('Home Page')
    end
  end
end

Factory Girl (TODO)

Running tests

Run all tests in spec/

$ rspec

Testing uploads with Carrierwave, Fog and FactoryGirl

https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Test-Fog-based-uploaders http://www.engineyard.com/blog/2011/mocking-fog-when-using-it-with-carrierwave/ http://pivotallabs.com/users/mgehard/blog/articles/1655-mocking-fog-when-using-it-with-carrierwave

Files

  • spec/support/fog.rb
  • config/fog_credentials.yml
  • config/initializers/carrierwave.rb
  • spec/files/picture.jpg

Twitter Bootstrap

http://railscasts.com/episodes/328-twitter-bootstrap-basics

Install

Add the gems.

group :assets do
  gem 'twitter-bootstrap-rails'
end

Initialize bootstrap.

rails g bootstrap:install

Stylesheets

Skip the default stylesheets when scaffolding.

rails g scaffold [ModelName] [attribute]:[type] --skip-stylesheets

Add bootstrap stylesheets to a resource

rails g bootstrap:themed [ModelName] -f

Be sure to use bootstraps css-classes, like "container", etc.

@marcusmalmberg
Copy link

It would be nice if you could add something about how to configure password mails with active admin.

Like:

# config/environments/production.rb
config.action_mailer.default_url_options = { :host => '<your host>' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
    :address  => 'smtp.gmail.com',
    :port     => 587,
    :domain   => '<your domain>',
    :user_name => '<username>',
    :password => '<password>',
    :authentication => 'plain',
    :enable_starttls_auto => true
  }

and

# config/environments/development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
config.action_mailer.delivery_method = :test

@john-patrik
Copy link
Author

john-patrik commented Jul 27, 2012 via email

@marcusmalmberg
Copy link

In: setup.mdand rvm.md
Instead of doing

$ cd ..
$ cd heroku-test

One can do

$ cd .

@marcusmalmberg
Copy link

There's no need to create the .rvm file first, like this:

echo 'rvm --create --rvmrc use 1.9.2@heroku-test' > .rvmrc

It will only create an old file that's never used. Instead run the command directly, like:

rvm --create --rvmrc use 1.9.2@heroku-test

@john-patrik
Copy link
Author

john-patrik commented Aug 1, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment