Best ruby-on-rails questions in April 2012

ActiveAdmin Error: no superclass method `buttons'

15 votes

I'm starting with Rails (and I'm also new with Ruby -coming from Python-) and I'm currentrly trying to setup ActiveAdmin for Rails 3.2.3 (Ruby 1.9.3). I'm following this guide but I was not able to run it properly. When I run the rails s command visiting localhost:3000/admin I get

NoMethodError in Active_admin/devise/sessions#new

Showing /home/lex/.rvm/gems/ruby-1.9.3-p125/gems/activeadmin-0.4.3/app/views/active_admin/devise/sessions/new.html.erb where line #11 raised:

super: no superclass method `buttons' for #<ActiveAdmin::FormBuilder:0xb429ae0>

I could not find anything useful on Google, what's wrong here?

If you need more info about this exception please tell me.

Extracted source (around line #11):

8:       f.input :password
9:       f.input :remember_me, :as => :boolean, :if =>  false  #devise_mapping.rememberable? }
10:     end
11:     f.buttons do
12:       f.commit_button "Login"
13:     end
14:   end

seems like formtastic 2.2.0 (released today) breaks active_admin and since active_admin requires formtastic >= 2.0.0... put in your Gemfile this

gem "formtastic", "~> 2.1.1"
gem "activeadmin", "~> 0.4.3"

then run

bundle update formtastic

then restart your server (if you have it running)..

and should work ok...

11 votes

I'm struggling to understand how Rails 3.2 applies layouts when using mountable engines.

Scenario: I'm building an engine which itself has a dashboard view and an admin view for various admin functions. I want the dashboard to have its layout overridable by the base application (if the user desires) but the admin should always use its own layout.

Here's what I have at the moment inside my engine;

application_controller.rb

module Myengine
  class ApplicationController < ActionController::Base

admin/dashboard_controller.rb

module Myengine                                                                                                          
  class Admin::DashboardController < ApplicationController

now I have my engines application.html.erb apply a hideous Red background whilst the base applications application.html.erb uses a pleasant yellow background so I can distinguish which application layout is being applied.

In this situation, if I access the base application first I see my yellow background (from the base app) and if I go to both the engine and the engines admin path the yellow background remains.

If I restart the server and access the engine first then I see the red background for the engine and the engines admin path whilst the base application shows the yellow background.

If I modify my admin/dashboard_controller.rb as follows;

module Myengine
  class Admin::DashboardController < ApplicationController
    layout 'myengine/application'

which I would expect to only apply to the engine/admin controller - but if I restart the server and access the engine/admin path I see the red background whilst the root view of the engine uses the base application yellow layout.

If I restart the server again and access the root of the mounted engine I get the red background applied which remains on the engines admin path too.

Aaaaarggggghhhhh!

Is it expected behaviour to have different layouts of the application used depending on which path of the application is accessed first? Surely not?? I must be doing something wrong!

I've debugged the problem and actually it's not a bug in Engines. The problem is caused by the way rails dependencies are loaded.

This code will behave differently in 2 scenarios that you're showing:

module Enginedemo
  class DashboardController < ApplicationController
  end
end

If ApplicationController is already loaded, rails will assume that we just want to use it and you will actually not inherit from Enginedemo::ApplicationController but from ApplicationController. In the other scenario, when you first load engine's controller, ApplicationController is not loaded yet, so Rails does the right thing.

Thankfully this problem occurs only in development environment as in production controllers are loaded when application is booting.

I'm not sure if this is something that can be easily fixed in rails dependencies, I will take a look at it.

For now, please explicitly require application controller:

require 'enginedemo/application_controller'

module Enginedemo
  class DashboardController < ApplicationController
  end
end

Omniauth and open_id with Google broken when running behind nginx in SSL mode

6 votes

Rails 3.0.12, newest omniauth, I can connect to Google and get the user's email address just fine. But then I run that same rails app behind nginx in SSL mode, and it fails with the Google page:

"The page you requested is invalid."

Is it my nginx config? My omniauth setup?

I know the X-Forwarded-Proto: https is the special sauce here, is there anything else I need to do to get openid happy behind an SSL web server?

Here's the full example code: you can clone this repo, bundle install, and run rails s to see it work just fine, then run rake server to see it fail. https://github.com/jjulian/open_id_ssl

nginx.conf:

worker_processes  2;
pid        tmp/nginx.pid;
error_log  log/error.log;
daemon     off;

events {
}

http {
  client_body_temp_path tmp/body;
  proxy_temp_path       tmp/proxy;
  fastcgi_temp_path     tmp/fastcgi;
  uwsgi_temp_path       tmp/uwsgi;
  scgi_temp_path        tmp/scgi;

  server {
    listen 3000 ssl;
    ssl_certificate      development.crt;
    ssl_certificate_key  development.key;
    ssl_verify_depth     6;

    access_log log/access.log;
    proxy_buffering off;
    location / {
      proxy_pass        http://127.0.0.1:3300;
      proxy_set_header  X-Real-IP        $remote_addr;
      proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header  Host             $http_host;
      proxy_redirect    off;
      proxy_set_header  X-Forwarded-Proto https;
    }
  }
}

omniauth.rb initializer:

require 'openid/store/filesystem'

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :open_id, :identifier => 'https://www.google.com/accounts/o8/id'
end

routes.rb:

OpenIdSsl::Application.routes.draw do
  match '/auth/open_id/callback' => 'accounts#update'
  match '/auth/failure' => 'accounts#failure'
  root :to => 'accounts#show'
end

UPDATE: This example used Rails 3.1.12 and OmniAuth 1.0.3. Upgrading to Rails 3.1.4 and OmniAuth 1.1.0 fixes the issue.

Found your problem, I am still trying to find something cleaner but here is the quick & dirty fix:

add this in your config/initializers/omniauth.rb:

class Rack::OpenID
  def realm_url(req)
    'https://localhost:3000'
  end
end

And now for the explanation: when the rack-openid gem builds the request to send to the google openid server it fails in one spot using the rails application access url and not the nginx one (wich uses ssl) resulting in this being sent to the openid server:

openid.realm:http://localhost:3001
openid.return_to:https://localhost:3001/auth/open_id/callback

The realm use the http url (rails url) while the return_to points to the right https url (nginx), when the openid server sees this it stops and return an error.

PS: I will edit the answer if I manage to find a cleaner way.

Ruby on Rails plural (controller) and singular (model) convention - explanation

6 votes

As per Ruby on Rails convention, controller names get pluralized while model names are singular. Example : a Users controller, but a User model.

rails generate controller Users
rails generate model User name:string email:string

Now open migration file

 class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :email    
      t.timestamps
    end
  end
end

Here table name is plural (users).

So my question is - Why table name is plural (users) even though the model name is singular (User)?

Ruby on Rails follow linguistic convention. That means a model represents a single user, whereas a database table consists of many users.

Recurring Events in Calendar - Rails

6 votes

I am searching for the best way to model recurring events. I am using fullcalendar to display events. But I guess recurring events are best handled on the rails backend.

I already looked at other questions and existing example code but I didn't find anything which fits.

It should behave similar like google calendar. So it should be possible to delete/modify single events of the recurring event series. But saving all events of the event series in the database seems inefficient. Also it should be possible to create single events without any recurrence.

What would be a good model architecture?

My event model right now looks like that (without additional attributes):

# Table name: events
#
#  id              :integer         not null, primary key
#  employee_id     :integer
#  created_at      :datetime
#  updated_at      :datetime
#  starts_at       :datetime
#  ends_at         :datetime
#

class Event < ActiveRecord::Base
  attr_accessible :starts_at, :ends_at
end

Here is how I would model this. I haven't used Google Calendar much, so I'm basing the functionality off of iCal's recurring events.

All models should have the usual id, created_at, updated_at properties. Listed are the custom properties. If the property is another model, you will implement it an association such as has_one or belongs_to.

  • RecurrencePeriod
    • Event base_event # has_one :base_event, :class_name'Event'
    • Time end_date # may be nil, if it recurs forever
    • WeeklyRecurrence recurrence # has_one :recurrence, :as=>:recurrence
    • Array[OccurrenceOverride] overrides # has_many :overrides, :class_name=>'OccurrenceOverride'

The RecurrencePeriod starts on the date that its base_event starts. Also, I assume that an Event's employee_id refers to the employee that created that event. A RecurrencePeriod will also belong to the employee that created the base_event.

The model depends on how flexibly you want to be able to specify recurrences. Are you going to support "Tuesday and Thursday every two weeks from 10 AM to 11 AM and from 2 PM to 3 PM" or just "repeats weekly"? Here's a model that supports just "repeats weekly", "repeats every two weeks", etc.; you can expand it if you need to.

  • WeeklyRecurrence
    • Integer weeks_between_recurrences
    • RecurrencePeriod recurrence_period # belongs_to :recurrence, :polymorphic=>true

I use polymorphic associations here, because I think they might be useful if you want more than one type of recurrence, such both WeeklyRecurrence and DailyRecurrence. But I'm not sure that they're the correct way to model that, so if they turn out not to be, just use has_one :weekly_recurrence and belongs_to :recurrence_period instead.

The Ice cube library seems like it might be useful for calculating recurrences. If WeeklyRecurrence above isn't powerful enough, you might just want to store an Ice cube Schedule object in a model, replacing WeeklyRecurrence. To store a Schedule object in a model, save it as an attribute "schedule", put serialize :schedule in the model definition, and generate a text column "schedule" in the database.

OccurrenceOverride handles the case of a single instance of a recurring event being edited.

  • OccurrenceOverride
    • RecurrencePeriod recurrence_period_to_override # belongs_to :recurrence_period_to_override, :class_name=>'RecurrencePeriod'
    • Time original_start_time # uniquely identifies which recurrence within that RecurrencePeriod to replace
    • Event replacement_event # has_one :replacement_event, :class_name=>'Event'; may be nil, if that recurrence was deleted instead of edited

Instead of storing each occurrence of an event individually, generate them temporarily when you need to show them in the view. In RecurrencePeriod, create a method generate_events_in_range(start_date, end_date) that generates Events, not to save in the database, but just to pass to the view so it can show them.

When a user edits a recurrence, they should have the option to modify all occurrences, all future occurrences, or just that event. If they modify all occurrences, modify the RecurrencePeriod's base_event. If they modify all future occurrences, use a method you should implement on RecurrencePeriod that splits itself into two RecurrencePeriods on either side of a certain date, and then save the changes to just the second period. If they modify only that event, create an OccurrenceOverride for the time that they are overriding, and save the changes to the override's replacement_event.

When a user says a certain event should now recur every two weeks for the foreseeable future, you should create a new RecurrencePeriod with that event as base_event and a nil end_date. Its recurrence should be a new WeeklyRecurrence with weeks_between_recurrence=2, and it should have no OccurrenceOverrides.

ide sublime2 how to find method definition

6 votes

I'm using Sublime 2 for Ruby On Rails programming. I need a ability to click a method name and jump to class where the method is defined. There are many IDE with similar capability...

Goto symbol is Ctrl-R (linux), this gives a pop-up-list of all symbol and class definitions in the file, in definition order, and you can jump to what you're after. You could do the same thing with Goto Anything, Ctrl-P and then typing @ and the method name.

Also, there is a Goto Symbol plugin, which lets you jump straight to the definition of the method name your cursor is at, with a key binding or click.

However, both those methods are limited to the current file. If you need to jump to definitions in other files, probably the best solution is the SublimeCodeIntel plugin. It seems to be working pretty well and just by hitting Ctrl-f3 (linux) will open up the file at the definition you want.

Retaining the pattern characters while splitting via Regex, Ruby

5 votes

I have the following string

str="HelloWorld How areYou I AmFine"

I want this string into the following array

["Hello","World How are","You I Am", "Fine"]

I have been using the following regex, it splits correctly but it also omits the matching pattern, i also want to retain that pattern. What i get is

str.split(/[a-z][A-Z]/)
 => ["Hell", "orld How ar", "ou I A", "ine"] 

It omitts the matching pattern.

Can any one help me out how to retain these characters as well in the resulting array

Three answers so far, each with a limitation: one is rails-only and breaks with underscore in original string, another is ruby 1.9 only, the third always has a potential error with its special character. I really liked the split on zero-width assertion answer from @Alex Kliuchnikau, but the OP needs ruby 1.8 which doesn't support lookbehind. There's an answer that uses only zero-width lookahead and works fine in 1.8 and 1.9 using String#scan instead of #split.

str.scan /.*?[a-z](?=[A-Z]|$)/
=> ["Hello", "World How are", "You I Am", "Fine"]

My .on() is acting like .bind(), not .live()

5 votes

I have a complicated nested form (Ryan Bates' version) with .live() attached to some of the dynamically generated elements, which I'm now transitioning over to .on() along with an upgrade from Jquery 1.4 to 1.7.

Here's a sample of one of the ~22 changes:

# old version with .live()
$('.options .image').live('click', function(){
    console.log('clicked .options')
})

# new version with .on()
$('.options').on('click', '.image', function(){
    console.log('clicked .options')
})

The changes work perfectly well for the form elements that already exist but they are failing for any nested elements that are dynamically created afterwards. Hence, it's working more like Jquery's bind than live. Do you know what might be going on here?

Due to the exceeding complexity of the code and lots of partials I'm leaving it out for now (hoping you might have a hunch!). Thanks.

As per 3nigma's comment but modified with your original selector, this will work:

$(document).on('click', '.options .image', function() {
  console.log('clicked .options');
});

However, I don't think setting document as listener is usually the way to go. In your original version with .live() you are selecting .image nodes within the .options node.

But the question doesn't say which parts are loaded dynamically. I suspect that .options is also part of the content that's loaded dynamically. The first selector when using .on() for delegating listeners has to be something that is NOT destroyed:

$('#someWrapper').on('click', '.options .image', function() {
  console.log('clicked .options');
});

#someWrapper doesn't need to be a new wrapper element, it can be any ancestor (what some people call a "parent"... but that's a misnomer since it can be a grandparent or great-grandparent or whatever!) that is not destroyed. The closer to the target selector (.options .image) the better.

Set with custom rule

5 votes

According to the Set doc, elements in a set are compared using eql?.

I have a class like:

class Foo
  attr_accessor :bar, :baz

  def initialize(bar = 1, baz = 2)
    @bar = bar
    @baz = baz
  end

  def eql?(foo)
    bar == foo.bar && baz == foo.baz
  end
end

In console:

f1 = Foo.new
f2 = Foo.new
f1.eql? f2 #=> true

But...

 s = Set.new
 s << f1
 s << f2
 s.size #=> 2

Because f1 equals f2, s should not include both of them.

How to make the set reject elements with a custom rule?

The docs that you link to say explicitly (emphasis mine):

The equality of each couple of elements is determined according to Object#eql?
and Object#hash, since Set uses Hash as storage.

If you add a hash method to your class that returns the same value for eql? objects, it works:

# With your current class

f1, f2 = Foo.new, Foo.new
p f1.eql?(f2)
#=> true
p f1.hash==f2.hash
#=> false
p Set[f1,f2].length
#=> 2

# Fix the problem
class Foo
  def hash
    [bar,hash].hash
  end
end

f1, f2 = Foo.new, Foo.new
p f1.eql?(f2)
#=> true
p f1.hash==f2.hash
#=> true
p Set[f1,f2].length
#=> 1

To be honest I've never had a great sense for how to write a good custom hash method when multiple values are involved.

How do you structure i18n yaml files in Rails?

5 votes

I started populating an en yaml file in Rails and I can already tell it will get messy and out of hand before too long. Is there a convention to keeping this file organized?

So far I have this structure:

language:
  resource:
    pages: # index, show, new, edit
      page html elements: # h1, title
  activerecord:
    attributes:
      model:
        property:

Now I have the following things that I want to fit into this structure but I'm unsure how to:

  1. Navigation
  2. Button text (save changes, create account, etc)
  3. Error messages from controller flash
  4. How to add multi-word keys. Do I use a space or an underscore? For exmaple, t(".update button")) or t(".update_button")

Is there a convention to locale file structure?

I've found that the best overall strategy is to somewhat reproduce the file structure so that given any translation, I can immediately find where it was called from. This gives me some kind of context for making the translation.

The majority of application translations are found in views, so my biggest top level namespace is usually views.

I create sub namespaces for the controller name and the action name or partial being used ex :

  • views.users.index.title
  • views.articles._sidebar.header

Both of these examples should make it obvious what part of my app we're translating and which file to look in to find it.

You mention navigation and buttons, if they are to be generic, then they belong in the views.application namespace just as do their view counterparts :

  • views.application._main_nav.links.about_us - a link in our app's main navigation partial
  • views.application.buttons.save
  • views.application.buttons.create - I have a bunch of these buttons ready to be used when needed

Flash messages are generated from the controller, so their top level namespace is... controllers! :)

We apply the same logic as we do to views :

  • controllers.users.create.flash.success|alert|notice

Again if you wanted to provide generic flash messages like "Operation successful", you would write something like this :

  • controllers.application.create.flash.notice

Finally, keys can be anything that is valid YAML, but please stick to using periods . as separators and underscores _ between words as a matter of convention.

The only thing left to sort out now, is getting rails' translations into its own namespace to clean up our top level :)

Dynamic nested form on change of select box

4 votes

I have used Ryan bates nested model form it is working fine,But
i have two models i,e storage and order both having nested model called items.

Storage:

has_many :orders  
has_many :items, :dependent => :destroy
accepts_nested_attributes_for :items

Order:

belongs_to:storage         
has_many :items, :dependent => :destroy
accepts_nested_attributes_for :items

In order view there is storage select box,

<%= f.select :storage_id,
            Storage.all.map{|s| [s.store_no, s.id]} %>

On selecting storage number respective items should appears in the Orders form with partial
can any body tell me the best way to do.

Thanks,

First you need to watch that input field to see it is changed. So, assuming:

  1. the Storage selector has an id of 'storage'
  2. the Storage selector has the id of the 'storage' as its value

...you could put this in your storage.coffee.js file:

jQuery ->
  $('select#storage').change ->
    storage_id = $('option:selected',this).val()
    $.get 'storages/' +storage_id+ '/orders.js'

Then, assuming that Orders are nested under storage, if your OrdersController looks like so:

OrdersController < ApplicationController

  def index
    @storage = Storage.find(params[:storage_id])
    @orders = @storage.orders
  end

end

...and if you have a partial app/views/orders/_order.html.erb...

...and if you have a div#orders on your page that you want the orders dropped into...

...then you should be able to make an app/views/orders/index.js.erb file like so:

$('div#orders').html('<%= escape_javascript(render @orders) %>');

This should render a copy of the partial for each instance of the orders that belong to a given storage and append it to the dom after the storage selector.

What's happening is: when the select menu is changed it fires a js GET request to the orders index for the given storage. Then that request will automatically attempt to serve up an index.js page, with the instance variables set in the controller available to that view. The js in that view will execute after whatever interpolated ruby is inserted, so you can use rails functions (like render @orders) and then the output of those gets injected into the dom via $('div#orders').html('your rendered orders will be inserted in here by rails').

Clearly you'll have to tweak this to fit your page, I'm just guessing as to what elements of your page are called etc., but this basic concept should work fine. Let me know if you have any questions.

Should class instance variables in Rails be set within a mutex?

4 votes

Let's say I've got a Ruby class in my Rails project that is setting an instance variable.

class Something
  def self.objects
    @objects ||= begin
      # some logic that builds an array, which is ultimately stored in @objects
    end
  end
end

Is it possible that @objects could be set multiple times? Is it possible that during one request, while executing code between the begin/end above, that this method could be called during a second request? This really comes down to a question of how Rails server instances are forked, I suppose.

Should I instead be using a Mutex or thread synchronization? e.g.:

class Something
  def self.objects
    return @objects if @objects

    Thread.exclusive do
      @objects ||= begin
        # some logic that builds an array, which is ultimately stored in @objects
      end
    end
  end
end

I'll take a stab.

Rails is single-threaded. Successive requests to a Rails application are either queued or handled by separate application instances (read: processes). The value of the class instance variable @objects defined in your Something class exists within scope of the process, not within the scope of any instance of your application.

Therefore a mutex would be unnecessary as you would never encounter the case where two processes are accessing the same resource because the memory spaces of the two processes are entirely separate.

I think this raises another question, is @objects intended to be a shared resource, if so I think it needs to be implemented differently.

Disclaimer: I may be completely off the mark here, in fact I sort of hope I am so I can learn something today :)