Posts Ruby on Rails: api collection helpers html select
by bseanvt
leave a comment
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)
<%= collection_select("states", "state_id",
State.participating,
"abbreviation", "name",
{:selected=> get_current_state_or_nil },
{:onchange=>"document.location='/states/'+this.value"}
) %>
#which will produce something like...
<select id="state_id" name="state[id]" onchange="document.location='/states/'+this.value">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
</select>
Select Distinct in Rails with Active Record
User.find :all, :select => "DISTINCT occupation"
Ruby on Rails: activtiy stream Facebook newsfeed polymorphic associations simple
by bseanvt
leave a comment
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 => 10, :conditions=>["created_at > ?", 1.day.ago]) + ForumPost.find(:all, :limit => 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 <%= render @activity_stream rescue nil %>
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.
Posts Ruby on Rails: link_to routes scoping twitter urls usernames views
by bseanvt
4 comments
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 => '/:user_id' map.resources :users, :except => [:show] map.user '/:username' :controller => 'users', :action => '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.
<%= link_to(status.title, status_path(status.user,status) %> # 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
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
in the head of your layout file.
You define forms usingĀ “semantic_form_for” like so…
<% semantic_form_for @user do |f| %>
<% f.inputs do %>
<%= f.input :login, :label => "Username", :hint => "Something short because it's in the url"%>
<% end %>
<%= f.buttons %>
<% end %>
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.
Ruby on Rails: annotations productivity rake tasks todo
by bseanvt
leave a comment
TODO and Custom Annotations in Rails Applications
While writing software it’s common to leave comments for your future self. For instance, if you have written some code but realize that it should be refactored to be more efficient, you may place something along the lines of “TODO: change active record find method and replace w/ a custom sql select finder “. With rails, if you follow this convention, you can get a list of your annotations with a rake task.
rake notes:todo
which will print out the file where the the todo was found along with the line number and the comment…
app/controllers/application_controller.rb: * [ 8] fix me
Rails defines several other annotation types for you
rake notes # Enumerate all annotations rake notes:fixme # Enumerate all FIXME annotations rake notes:optimize # Enumerate all OPTIMIZE annotations rake notes:todo # Enumerate all TODO annotations
And you also may define your own
# SEAN: please rewrite this method to query only chunky bacon
you may find all instances of “SEAN” by running
rake notes:custom ANNOTATION=SEAN
Programming Ruby on Rails: active record classify constants initialize load models rake Ruby on Rails
by bseanvt
leave a comment
Load All ActiveRecord::Base Model Classes in Rails Application
Here is a simple rake task which will instantiate all of your Active Record models, provided that they are located in the RAILS_ROOT/app/models directory. Interestingly, all plugin models are instantiated by default when you run the task, for instance, if you are using the Acts As Taggable On plugin, you have access to Tag, Tagging without having to include the plugin models directory path to the task.
namespace :load_ar do
desc "load up all active record models"
task :models => :environment do
models = ActiveRecord::Base.send(:subclasses)
Dir["#{RAILS_ROOT}/app/models/*"].each do |file|
model = File.basename(file, ".*").classify
models << model unless models.include?(model)
end
end
end
If your’re in the console, you can get all the load paths for your Active Record models with the following from the API.
Rails.configuration.load_paths.each do |path| p path end
Programming Ruby on Rails: files nil partial render rescue
by bseanvt
leave a comment
Render Partial if File Exists
If you ever want to render a partial but don’t want an error thrown you can either check for the existence of the file first
<%= render :partial => params[:controller]+"/sidebar" if File.exists?(RAILS_ROOT+"/app/views/"+params[:controller]+"/_sidebar.html.erb")%>
or you can catch the error that Rails throws
<%= render :partial => params[:controller]+"/sidebar" rescue nil %>
Ruby on Rails: before_filter breadcrumbs hacks navigation referers restful sessions
by bseanvt
1 comment
Very Simple Breadcrumb Navigation in Rails with Before_filter
This may not be the ideal solution. This just manages request.referers in a session variable, then looping over each unique path prints a link to the screen. It’s more of a “history” than a hierarchy for resources in an application. It is however, pretty straight forward to implement.
First create a before_filter in your application controller.Call it on every action. In the definition we’ll parse the request.referer variable with the URI::parse method so that we’re only dealing with the relative, not absolute, resource. We’ll make sure that we’re only storing unique paths and if the user arrives at an index action, we set the session[:breadcrumbs] variable to nil. This indicates that they are at the top level.
#app/controllers/application_contoller.rb
#...
before_filter :setup_breadcrumb_navigation
protected
def setup_breadcrumb_navigation
if params[:action] == "index"
session[:breadcrumbs] = nil
else
url = URI::parse request.referer
if session[:breadcrumbs].nil?
session[:breadcrumbs] = url.path.strip
else
session[:breadcrumbs] = session[:breadcrumbs] + ", "+url.path if session[:breadcrumb]
end
session[:breadcrumbs] = session[:breadcrumbs].split(", ").uniq.join(",")
end
end
end
The helper function just splits apart the string stored in the session[:breadcrumbs] variable, looping over the relative paths. We link to them, but first replace the ugly “/” and preface the display with some form of delimiter. I chose to use the “::” which looks nice to me.
#app/helpers/application_helper.rb
def breadcrumbs
content_tag :span, :id=>"breadcrumbs" do
if not session[:breadcrumbs].blank?
session[:breadcrumbs].split(",").uniq.map{ |breadcrumb|
link_to(" :: "+breadcrumb.to_s.gsub("/"," ")+"",breadcrumb)
}
end
end
end
This is definitely a hack. You won’t necessarily find a hierarchical relationship between links in the breadcrumb navigation. However, it will display the users history letting them quickly access a resource they just visited a page or two before. It’s perhaps 80% of the functionality for only 5% of the work.
Oh yeah, putting this in a view
# app/views/layouts/application.html.erb <%= breadcrumbs %>
Ruby on Rails: controllers map namespace nested resources rest routing
by bseanvt
leave a comment
Nesting Resources in Rails Routes.Rb with Namespaces
When I have a controller that takes more than one has_many argument, I think about creating a namespace. This way I may still use my forums, pages controllers w/out needing any conditional logic, testing for the presence of :course_id in the params hash.
#config/routes.rb map.namespace :courses, :path_prefix=>'/courses/:course_id' do |courses| courses.resources :forums courses.resources :pages end map.resources :courses map.resources :forums map.resources :pages
# some view.html.erb <%= courses_forums_path(1) %> /courses/1/forums <%= courses_pages_path(2) %> /courses/2/pages # w/ use in a form don't forget to pass an array instead of just the resource (will map to forums_controller) <%=form_for [:courses, Forum.new] do |f| %><%end%>
in the namespaced controller you can extend the parent controller (if you like) to have access to methods coursescontroller defines.
# app/controllers/courses/forums_controller.rb class Courses::ForumsController < CoursesController before_filter :require_course_login #defined in parent ../courses_controller.rb def index end end
to use the generator to create namespaced controller
./script/generate controller 'courses/forums'