Notes posted to Ruby on Rails
RSS feedOn destroying data
Reply to tvle83 and pgmcgee: the destructiveness of this method depends on your database. Some databases are better at converting between disparate types than others. For example, when changing a column from a numeric type to a string type, some databases drop the data where others will turn the numbers into their string representations.
Essentially, YMMV.
a misprint?
In section ‘Bi-directional associations’ an example:
d = Dungeon.first
t = d.traps.first
d.level == t.dungeon.level # => true
d.level = 10
d.level == t.dungeon.level # => false
Then use has_many associations, but lower than written ‘for belongs_to associations has_many inverse associations are ignored.’
rest of code is in Object#try
The logic for #try is shared between this method and Object#try – “Show source” here doesn’t show the whole story. Both methods are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .
rest of code is in NilClass#try
If you click “Show source” here, you may get confused. The logic for #try is shared between this method and NilClass#try . Both versions are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .
Skipping validation - follow up
For Rails 2.x use #save(false) for Rails 3.x use #save(:validate => false)
Set ids when using a collection of values (cont.)
Regarding schmidt’s post.
The following will not have the expected behavior:
<% Car.each do |c| %> <%= check_box_tag "car_ids[]", c.id, :id => "car_ids_#{c.id}" %> <% end %>
But, if you put the “checked” option to false (or true), it will.
<% Car.each do |c| %> <%= check_box_tag "car_ids[]", c.id, false, :id => "car_ids_#{c.id}" %> <% end %>
Changing the Message
For Change the default message:
Code example
validates :invoice_number, :presence => {:message => 'The invoice number must be informed.'}
conditional rescue_from
Would it be possible to do something like:
rescue_from Exception, :with => my_handler, :unless => request.local?
Checking content_for
@tordans You asked your question 3 years ago, but in any case, should anyone have that same issue, you can manage that with:
- unless content_for(:footer).blank? yield(:footer) - else == render "layouts/footer_big"
content_for(:x) defaults to an empty string, that’s why you need to check for blank? not nil?.
this has been deprecated; see linked note
This has been deprecated. See this note on memoize : http://apidock.com/rails/ActiveSupport/Memoizable/memoize#1317-this-has-been-deprecated-replace-with-Memoist
this has been deprecated; replace with Memoist
In Rails 3.2, memoize has been deprecated. In edge Rails, it has been removed.
The commit when it was deprecated: http://github.com/rails/rails/commit/36253916b0b788d6ded56669d37c96ed05c92c5c
A Stack Overflow question about this change: http://stackoverflow.com/q/9132197/578288
I personally disagree with the removal of memoize, and don’t recommend using the `||=` pattern Rails now suggests. The exception is if your entire program only memoizes something once or twice, so it’s not worth including a gem for.
The easiest way to keep using memoize is to use the Memoist gem (http://github.com/matthewrudy/memoist , http://rubygems.org/gems/memoist), which is a simple extraction of ActiveSupport::Memoizable into its own gem.
Adding Additional Parameters to form_for
If you want to add additional parameters to the form_for helper, but still want to use one form for both your “create” and your “update” actions, you can add the additional parameters to the :url option, but you need to omit the :controller and :action keys.
form_for(@user, :url => {:param1 => "value1", :param2 => "value2"}) do |f|
or
form_for([@post, @comment], :url => {:param1 => "value1", :param2 => "value2"}) do |f|
where param1 and param2 are not :controller or :action
Another usage example
given: order active record class with “state” string field
class Order < ActiveRecord::Base def state @state ||= ActiveSupport::StringInquirer.new(read_attribute(:status)) end end order = Order.new(state: "initial") order.state.initial? #=> true order.state.paid? #=> false
add_to_base in Rails 3
In addition to stevo’s note, in Rails 3 you can also do:
model_instance.errors.add(:base, "Msg")
Month-first date string no longer parses correctly
The following date format won’t be parsed correctly:
'06/15/2008'.to_date
Use this instead:
Date.strptime("6/15/2012", '%m/%d/%Y')
Example of usage
e.g.
str = ActiveSupport::StringInquirer.new('test') str.test? # => true str.foobar? # => false
:disable_with is deprecated
Or you can use this way:
<%= submit_tag "Login", data: { disable_with: "Please wait.." } %>
:disable_with is deprecated
Since version 3.2.5 you should not use :disable_with.
Use this:
<%= submit_tag "Login", 'data-disable-with' => "Please wait.." %>
This method does not work.
It’s an old problem, reported back in 2010, just reopened issue:
Accepted parameters for validate
Validate method also accepts :on and :if parameters. The default value for :on is :save, the other accepted values are :create and :update
class Comment include ActiveModel::Validations validate :must_be_friends, :on => :create, :if => Proc.new {|comment| some_condition} def must_be_friends errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee) end end
similar to clone
See the clone documentation. I see that ActiveRecord is moving from “clone” (3.0.9) to “dup” (?).
Beware nested with_options clobbers!
Careful:
with_options :foo => :bar do |something| something.with_options :foo => :baz do |inner| what_is(:foo) end end
:foo will be :baz. It will not be [:bar, :baz], for example.
This bit me when trying to do nested with_options for validation where both had :if => something.
If you try to use :id as a non-primary-key field
If you’re using this so that you can repurpose :id for another use, it gets hairy: your ActiveRecord::Base subclass will still use :id to refer to your primary key, whatever it be named.
So when you call [my obj].id = 33, 33 is set as the value of your primary key, not your :id attribute!
STI - Making callbacks trigger in inherited classes
Assuming we have
class ParentClass < ActiveRecord::Base attr_accessible :type end class ChildClass < ParentClass after_save :perform_something end
Executing
ParentClass.create({:type => "ChildClass"})
will not trigger ChildClass callbacks. What is more, it will return instance of ParentClass instead of ChildClass.
To resolve this issue, you need to define following module
module ActiveRecord module CallbacksAwareSti extend ActiveSupport::Concern module ClassMethods def new(*args, &block) return super(*args, &block) unless args.first.respond_to?(:with_indifferent_access) type = args.first.with_indifferent_access[:type] if type.blank? or (type = type.constantize) == self super(*args, &block) else super(*args, &block).becomes(type) end end end end end
and include it in parent class
class ParentClass < ActiveRecord::Base include ActiveRecord::CallbacksAwareSti attr_accessible :type end
Inspired by http://stackoverflow.com/questions/4518935/activerecord-problems-using-callbacks-and-sti
block only and except
Code
class Journal < ActionController::Base # Require authentication for edit and delete. before_filter :authorize, :only => [:edit, :delete] # Passing options to a filter with a block. around_filter(:except => :index) do |controller, action_block| results = Profiler.run(&action_block) controller.response.sub! "</body>", "#{results}</body>" end private def authorize # Redirect to login unless authenticated. end end
Hidden Field Example
Here’s a pseudo code example of a hidden field within an ERB template. A post has many comments and this comment form is in a post’s show view. This would set a comment’s post_id attribute.
<%= form_for(@comment) do |f| %>
<%= f.hidden_field :post_id, :value => @post.id %>
<% end %>
method to use instead
This may be obvious, but the replacement for this method is csrf_meta_tags.
Example from Code School
module Tweets
class ShowPresenter extend ActiveSupport::Memoizable def initialize(tweet) @tweet = tweet end def username @tweet.user.username end def status @tweet.status end def favorites_count @tweet.favorites.count end memoize :username, :status, :favorites_count end end