Mongoid recursively embedding

This is a note for myself for a project I am actually working on that I thought could be useful to share :)

More info here.

CYCLIC RELATIONS on MONGODB WITH MONGOID

A document can recursively embed itself using recursively_embeds_many, which provides accessors for the parent and children.

class Tag
  include Mongoid::Document
  recursively_embeds_many
  field :name
end

programming = Tag.new(:name => 'programming')
ruby = programming.child_tags.build(:name => 'ruby')
python = programming.child_tags.build(:name => 'python')

programming.child_tags  # [ruby, python]
ruby.parent_tag         # [programming]
python.parent_tag       # [programming]

Updating embedded child objects when the parent object is saved.

Mongoid has added a tag which automatically makes callbacks for embedded child objects when the parent object is saved.

You can find it at the end of the mongoid documentation on embedding.

class Post
  include
Mongoid::Document
  include
Mongoid::Timestamps
  include
Mongoid::Paranoia

  embeds_many
:comments, cascade_callbacks: true
  accepts_nested_attributes_for
:comments
end

Devise + Mongoid + Cancan

I have thought a while about making a summary post about configuring devise + mongoid + cancan for creating accounts and implementing authentication in a rails app.

First of all there are various guides that you can use to get you started. All of them can give you a different insight on the technology and a different perspective and what is needed to accomplish whatever you have in mind :).

So feel free to google for devise + cancan and you end up reading Tony Amoyal’s blog post. It is a very good post description and pointed me toward the right direction.

If you want a different point of view though (also considering that I am using mongoid), here is my dirty summary on how to configure an app that would use these gems:

First of all install devise:

Devise 2.0 works with Rails 3.1 onwards. You can add it to your Gemfile with: gem ‘devise’ or run the bundle command.

After devise has been installed, run the generator:

rails generate devise:install

The generator installs an initializer describing All devise’s configuration options and it is advised to have a look at it. Then add devise to your models using the generator:

rails generate devise MODEL 

More details are available herehttps://github.com/plataformatec/devise; together with links to some example app that could be extended to suit your needs.

Now let’s install cancan. In Rails 2 you can add it to your Gemfile and or run the bundle command:

gem "cancan"

Continue with using the generator for creating the Ability class for a User:

rails g cancan:ability

Simple as that. You can find out more here.

Now how should you model your User and Admin accounts? You can do this with a single user class, or you can do it with different classes :).

I personally prefer to use different classes to keep the two roles separately.

Quick and dirty search in Rails

Ever wondered how to quick have a search function in your rails app?

Here is a super quick and maybe a lil dirty way to achieve so.

First step:

The view


 <p><%= form_tag("/searches", :method => "get") do %>

           <%= text_field_tag :keywords, params[:keywords] %> </p>

       <p>  <%= submit_tag("Search") %>

           <% end %>

       </p>

Second step:

search.rb model (app/models)

class Search < ActiveRecord::Base

  def self.find_results(search)

    if search

      Item.find(:all, :conditions => ['name LIKE ?', "%#{search}%"])

    else

      Item.find(:all)

    end

  end

end

Third step:

searches_controller.rb (app/controllers)

class SearchesController < ApplicationController

  def index

    @results = Search.find_results(params[:keywords])

  end

end

Fourth step:

index.html.erb (app/views/searches)

<% @results.each do |result| %>

             <p><%= result.name %></p>

Done :)

Just don’t forget to add   resources :searches, :controllers => ‘searches’ to your routes.rb!