01 Janoferear.com

Sunday, 01 January 2012 — 18:44

oferear.com is born in Zaragoza, Spain, in 2011. The initial project idea was awarded in the 1st edition of “Semillero de Ideas” promoted by Zaragoza council. A learning process of 6 months was started, where current version was developed.

oferear.com is a community of localized and categorized offers, created by users.

Particular users, professionals, small and big companies, can publish offers of their products and services in the web site for free. Furthermore, any user can let other users know about the existence of other interesting offers that haven’t been published yet. Just share the offer in the web site, or even easier, using mobile applications available soon. Users that discover more offers for the benefit of others, will get especial privileges, gain greater recognition, discounts in our associated companies or free access to premium services.

oferear.com includes an alert system for registered users, that will notify users by email as soon as there is a new offer of interest in the area and category specify by the user. For business and professionals that have published their offers in the web site, oferear.com will provide tools for tracking, highlighting or making the offer more visible.

07 DecCalculate difference in months between two dates in Javascript

Wednesday, 07 December 2011 — 13:25

Here i let you some code i wrote for this task:

calculateTotalMonthsDifference = function(firstDate, secondDate) {
        var fm = firstDate.getMonth();
        var fy = firstDate.getFullYear();
        var sm = secondDate.getMonth();
        var sy = secondDate.getFullYear();
        var months = Math.abs(((fy - sy) * 12) + fm - sm);
        var firstBefore = firstDate > secondDate;
        firstDate.setFullYear(sy);
        firstDate.setMonth(sm);
        firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
        return months;
}

10 OctI18n in Javascript files with Rails 3

Monday, 10 October 2011 — 09:03

With all the new techniques in Rails 3 for UJS, i was expecting an easiest way for also integrating I18n in javascript files (I mean real javascript files, not javascript templates). I was expecting for instance, the same way we can create css.erb files, i could do the same with js files. But this doesn’t seem to work. So we need to resort to external libs. In this case this gem was of tremendously help. Let’s see in detail:

1. Add this to your Gemfile (i like to add the link for further reference):

# https://github.com/fnando/i18n-js
gem "i18n-js"

2. Install the gem

bundle install

3. Set it up with this command. We will get a i18n-js.yml in our config file

rake i18n:js:setup

4. I recommend you edit the file and export just what you need. This is mine for instance, as i only need en and es files:

translations:
    - file: "app/assets/javascripts/i18n/translations.js"
      only: ['en.*', 'es.*']

IMPORTANT NOTE: Format here is important. Make sure the “only” line is perfectly tabbed under “f” letter of “file” line

5. Generate javascript file for specified languages. In development all the changes you make to your language files, will be automatically available in your javascript file. So i recommend you add this as part of your deployment to production scripts

rake i18n:js:export

6. Make js file available. Add this to your application.js (add the language file you generated, in my case translations)

//= require i18n
//= require i18n/translations

7. We’re almost done. We only need an additional step for loading locale and have it available from javascript file. We need to know which is user’s locale. We will make this possible adding this to our application.html.erb file before any other javascript file:

<script type="text/javascript">
      I18n.defaultLocale = "<%= I18n.default_locale %>";
      I18n.locale = "<%= I18n.locale %>";
</script>

8. Now we’re ready!. You will have I18n available with commands like:

I18n.t("scope.literal")

Find more options available on author’s gem website here

Ger

23 AugHuman readable URLs with Friendly_id in rails 3

Tuesday, 23 August 2011 — 21:44

If you follow rails standards, most of your routes for showing, editing, updating or deleting records from your tables, will depend on the record_id. For example, if you have users in your application, you can get the list of them by yourdomain.com/users. And you get a specific user with yourdomain.com/users/3, where 3 is the user.id value.

There are some cases, where it’s interesting to have human readable urls. Let’s think we want to have places than can be shared between friends. What would you prefer for sharing? a url like: yourdomain.com/places/times_square_new_york, or a url like yourdomain.com/places/1 ?

Just this is what i pretended with my project, and here i will explain how easy can it be to accomplish. Slugify is basically a term that defines the process of getting a human readable word from a string. In the previous case, we are getting the slug from place definition (Times Square, New York).

There are different alternatives available to accomplish this. You can get a list of the most popular ones here. I have to admit that i was looking at different alternatives, and i finally chose friendly_id because of its potential and popularity. I tested it and it really works fine to me.

Let’s see the steps:

1. Add the gem to your Gemfile and run bundle

+# Slug. https://github.com/norman/friendly_id
+gem "friendly_id", "~> 4.0.0.beta8"
> bundle

2. Get our model ready. Let’s think the model is Places.

class Place < ActiveRecord::Base
  extend FriendlyId 
  
  friendly_id :location, :use => :slugged

end

3. Create a migration file for adding a new slug column to our model. You can use the special syntax for doing it automatically

rails generate migration add_slug_to_places slug:string

You will get a migration file that adds that column automatically. But i finally edited it a little bit. Make it look like this:

class AddSlugToPlaces < ActiveRecord::Migration
  def self.up
    add_column :places, :slug, :string, :unique => true, :null => false
    Place.all.map(&:save)
    add_index :places, :slug, :unique => true
  end

  def self.down
    remove_index :places, :slug
    remove_column :places, :slug
  end
end

I’m adding the new slug column to places table, as well as creating some constraints at database level. Then i’m re-saving all the existing Places i have in the database. With this, i’m making sure all the places are slugified. Before we save a new record, the slug is computed, so after adding the slug column to the table, i want to have it filled with the slug. If you don’t have any record yet on the table, you can comment that line out. I just had a couple of them, so for easiness i preferred to go that way. If you have more, i recommend to use a rake task for that.

This step is essential to accomplish the last action. We are creating a new index over the unique value of the slug. We can’t have two identical slugs in our application. So we firstly compute them, looking at location column. The gem will make sure they are not repeated.

4. Now you can ran migrations

rake db:migrate

5. Lunch your server and get ready for the magic. You are done!

rails s

Note aside. I like to have some before_filter actions on edit and destroy actions of model_controller. Those are really sensitive actions that you need to be really cautious. I like to make sure the user that pretends to remove or edit that particular record is the owner of that record. I’m doing that with something like in the controller

before_filter :validate_owner, :only => [:destroy, :edit]

def validate_owner
    unless current_user.places.exists?(params[:id])
      redirect_to(places_path)
    end
  end

Ok, it’s likely that you get redirected to places_path because of friendly_id gem. I reported that to Norman, and you can find all the info here

EDIT: As a temporal fix, you can replace the exists? with:

def validate_owner
    unless current_user.places.where("slug = :id OR id = :id", {:id => params[:id]}).limit(1).select(1)
      redirect_to(places_path)
    end
  end

23 Juluninitialized constant MyModule::MyClass in Rails 3

Saturday, 23 July 2011 — 23:02

If you ended up in this blog because of the exception uninitialized constant MyModule::MyClass on a Rails 3 application i hope you can find the solution here.

The error message is self explanatory. What is not that obvious is where the problem is. Basically, the Rails is not able to find your class.

The first thing you should check, is its name, and folder/s containing your class. For instance, if you have something like this (myclass.rb):

module MyModule
    class MyClass;  end
end

you can call MyClass in this way:

MyModule::MyClass.new

so far, so good. But there can be situations, where this will not work. Take into account this schema:

/lib
  /my_module
    klass1.rb
    ...
    utils.rb
  /utils
    klass2.rb

Next code in klass1.rb will fail:

def do_something
  Utils::Klass2.new
end

As you are in Utils class, it tries to find Klass2 constant in that scope, and obviously can’t find it. I guess you got it. To fix these situations, you have 2 options. Change the name of your modules/files, or use :: to reference root (you’d better go through first approach for a more stable solution though):

def do_something
  ::Utils::Klass2.new
end

However, this is not the problem on most of the cases. Did you enable autoload paths in config/application.rb file?. If you want to autoload your classes under lib directory, make sure you have something like this (config/application.rb):

# Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += %W(#{config.root}/lib)

And finally, if anything before fixed your problem, make sure you restart your server :)

Ger