Execute Javascript When Using Link_to_function To Include a Partial in Rails

If you use the link_to_function to replace content in a div with content from a partial, any javascript that you include in the partial will not be executed. It is instead included, but will do nothing. Obviously, this isn’t the desired behavior. Why would we be taking the trouble to write the javascript in the partial? There is an easy fix. Instead of writing out the script tags, instead use the javascript_tag  method to wrap whatever javascript you would like executed when the partial is loaded.

<%=link_to_function "say hello" {|p| p.replace_html "container", :partial => "say_hello" }%>

And now in my say_hello.erb file

<% javascript_tag do %>
  alert("Hello World");
<% end %>

Rails Select Tag and Onchange Event Calling a Remote Function with Default Option Selected

Here is a little code snippet that will fire off a request to update_client_path when you change the select field. This stands alone, rather than being apart of a larger form. The Client::CATEGORY argument is a hash, which I populated manually in my Client.rb model. It is something like this

CATEGORY = {:lead => "Prospective clients", :past => "Previous clients..."}

In my view I have

<%= select_tag "client_category",
 options_for_select(Client::CATEGORY.keys, @client.category.to_sym),
 { :onchange => remote_function( :url => update_client_path(@client), :with=>"'change_to='+this.value+''" ) } %>

One gotcha is that the select_tag, options_for_select argument expects a symbol if you’re passing in a hash as the type of the collection! It may not set the default if you provide it with a string for the second arg (which specifies which option should be set as selected).

You also need to make sure that the url update_client_path is set in your routes file and that your controller (clients_controller in this case) has the appropriate method to handle the request.

Ruby Enterprise Edition and Passenger ./script/console production fails and instead returns Loading production environment (Rails 2.3.5) Rails requires RubyGems >= 1.3.2. Please install RubyGems and try again: http://rubygems.rubyforge.org

After installing Ruby Enterprise Edition, REE, and Passenger on Ubuntu you may see this error message when you run script/console for the first time

./script/console production
# =>
Loading production environment (Rails 2.3.5)
Rails requires RubyGems >= 1.3.2. Please install RubyGems and try again: http://rubygems.rubyforge.org

You then scratch your head and run

which gem
which ruby
which rails

to find that all appears to be in order. You have rubygems installed , ruby is installed and so is rails. You also find that each are pointing to the correct location, which is something like /usr/bin/gem -> /opt/ruby-enterprise-x.x.x.x/bin/gem, where x.x.x.x is the version of REE.

The problem isn’t however, with any of the above. The issue is with the location of irb. If you installed (like me) irb with apt-get install irb, then irb isn’t aware of your shiny new REE and ruby gems. It’s a simple fix however, unlink irb and symlink the /usr/bin/irb to REE’s irb like so…

rm /usr/bin/irb

And symlink it to the irb that REE has in bin

ln -s /opt/ruby-enterprise-x.x.x.x/bin/irb /usr/bin/irb

Now cd into your rails app and run

./script/console production

Renaming Routes in Rails 3 with :As and :Controller

Renaming routes in Rails 2.* is straight forward. It goes something like this.

## config/routes.rb
map.resources :users, :as => :members

This will give you users_path and form_for(User.new) helpers, for instance, mapping the url to /members instead of /users while using the users_controller.rb class.

In Rails 3.*, this is still possible. It is accomplished differently. In my opinion, it seems a little less elegant.

# config/routes.rb
resources :members, :as => :users, :controller => :users
# app/views/**/*.erb
link_to "Members", users_path
form_for User.new do |f|
# Rake routes
       users GET    /members(.:format)           {:controller=>"users", :action=>"index"}
       users POST   /members(.:format)           {:controller=>"users", :action=>"create"}
    new_user GET    /members/new(.:format)       {:controller=>"users", :action=>"new"}
   edit_user GET    /members/:id/edit(.:format)  {:controller=>"users", :action=>"edit"}
        user GET    /members/:id(.:format)       {:controller=>"users", :action=>"show"}
        user PUT    /members/:id(.:format)       {:controller=>"users", :action=>"update"}
        user DELETE /members/:id(.:format)       {:controller=>"users", :action=>"destroy"}

Your resource is “members” and you are overriding the name (using :as=>”users”) however, you still have to specify the controller.

http://pastie.org/1154956

8 Sep 2010, 3:57pm
Ruby on Rails
by

leave a comment

Using to_sentence method on an Array in Ruby on Rails

Member.all.collect {|member| member.firstname}.to_sentence
=> "Alex, Andy, and Sean"

Declare separator and the connector

Member.all.collect {|member| member.firstname}.to_sentence(
  :connector => "and last but not least,",
  :skip_last_comma => true
)
=> "Alex, Andy and last but not least, Sean"

Collection Select Helper and OnChange Event in Rails

Given a collection of Active Record objects, you may use the collection_select helper method to produce a select form field. You need to pass in a number of arguments to the helper function.

1) object – your model object used in the collection
2) method – a valid model attribute or method
3) collection – a collection of active record model objects
4) option_value – value being set from the model for the <option value=”option_value”> html element
5) option_name – what is displayed for the user e.g., <option> option_name <
6) option – general options
7) options for the select html element

# helper and arguments...
# collection_select( model, id, collection, option_value, option_name, options, html_options)

&lt;%= collection_select("states", "state_id",
  State.participating,
  "abbreviation", "name",
   {:selected=&gt; get_current_state_or_nil },
   {:onchange=&gt;"document.location='/states/'+this.value"}
) %&gt;

#which will produce something like...

<pre id="line27">&lt;select id="state_id" name="state[id]" onchange="document.location='/states/'+this.value"&gt;
&lt;option value="AL"&gt;Alabama&lt;/option&gt;
&lt;option value="AK"&gt;Alaska&lt;/option&gt;
&lt;option value="AZ"&gt;Arizona&lt;/option&gt;
&lt;option value="AR"&gt;Arkansas&lt;/option&gt;
&lt;/select&gt;

Select Distinct in Rails with Active Record

User.find :all, :select => "DISTINCT occupation"

Simple Activity Stream Implementation in Rails

There are many ways to tackle the Facebook style activity stream feature for your app. The simplest approach, which you can tack on at almost any moment, is what I’ll describe here. You don’t have to create a new model for news feed items or create any polymorphic associations. You simply query for the records on separate models you would like aggregated in the stream, and render a partial for that record, which Rails will map for you.

# in app/controllers/home_controller.rb
def index
 @activity_stream = (Forum.find(:all, :limit =&gt; 10, :conditions=&gt;["created_at &gt; ?", 1.day.ago]) + ForumPost.find(:all, :limit =&gt; 10)).sort_by {|item| - item.created_at.to_i}
end

The sort_by method at the end places all of your feed item into descending chronological order. Omit the minus sign and they will be sorted in ascending order.

sort_by {|item| - item.created_at.to_i} # in descending chronological order

Show your latest activity in your views…

#app/views/home/index.html.erb
&lt;%= render @activity_stream rescue nil %&gt;

This assumes that you will have created the partials for each resource using Rails conventions i.e., you have in created the partials for the models like so app/views/_[the model name].html.erb. In this instance, you should have app/views/forums/_forum.html.erb and app/views/forum_posts/_forum_post.html.erb

You can rename the partials to something like _stream_forum.html.erb, if you already have the forum partial gainfully employed. You’ll need to change the view and prob. throw it into a loop to either check for a condition or use _stream_[model name].html.erb as the convention for any stream items.

Scope Routes/URLs By Username (like Twitter) in Your Rails Application

There are a few things that need to be taken care of before you can get this to work. The first thing (although, any of the following steps can be done in any order) to take care of involves your User model. You need to override the to_param method, so that Rails will appropriately use the username attribute rather than user_id when constructing paths.

#in app/models/user.rb
def to_param
  "#{self.username}"
end

Next we move onto routing our resources. Here it gets a little tricky because Rails is building paths for us. Remeber, you can get a list of all currently defined routes in your application by running the routes rake task

rake routes

We need to set the path_prefix option on any of our resources we want scoped by the username. For instance, in this example, I have set up a Status model and statuses_controller, whose urls shall be scoped by the username. You can apply the path_prefix to any number of other resources in your routes config file. They symbol used is arbitrary, but will be made available in the params hash, in this case params[:user_id]. You also need to exclude the show action on your users resources declaration. The reason is that, otherwise, Rails will include the controller name in the path like /users/username, which doesn’t look as clean as just /username. You then need to redefine this route explicitly (last line in the routes config shown here).

#in app/config/routes.rb
map.resources :statuses,   :path_prefix =&gt; '/:user_id'
map.resources :users,     :except =&gt; [:show]
map.user '/:username' :controller =&gt; 'users', :action =&gt; 'show'

Finally, you get to call these routes in your views or use them in your controllers. You use the same link_to, url_for methods to generate paths. When constructing the resources you have setup with the path_prefix declartion, remember you need the user model as the first argument, followed by said resource.

&lt;%= link_to(status.title, status_path(status.user,status) %&gt;
# or in a controller
redirect_to status_path( status.user, status )

That’s pretty much it. If anyone has another way of doing this let me know!

Using Formtastic to Cleanly Create Nice Looking Forms in Rails

Forms can easily get cluttered when you’re dealing with a lot of form fields… er, ERB tags. I’ve written about extending Rails form builders, which certainly goes along way to shrinking your views where forms are used. The plugin Formtastic is even better, as it lets you skirt maintaining your own library in favor of a very, elegant DSL.

For a great overview of the plugin and implementation details, check out Ryan Bate’s Railscast. There are a couple episodes, but be sure to catch the first one, linked above.

I usually install the plugin as a gem

# config/environment.rb
#...
config.gem "formtastic"

and then run a generator to create the stylesheets for me, making forms look nice and neat.

./script/generate formtastic

One gotcha, is that in order for the css to render correctly you need to add this

&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;

in the head of your layout file.

You define forms using  “semantic_form_for” like so…

&lt;% semantic_form_for @user do |f| %&gt;
  &lt;% f.inputs do %&gt;
    &lt;%= f.input :login, :label =&gt; "Username", :hint =&gt; "Something short because it's in the url"%&gt;
  &lt;% end %&gt;
  &lt;%= f.buttons %&gt;
&lt;% end %&gt;

As per usual, there are a myriad of configuration options which can be overridden if necessary. Consult the documentation at Justin French’s Github account for specifics.