71

I'm using rails and I want to make it so that attr_accessor :politics is set, by default, to false.

Does anyone know how to do this and is able to explain it in simple terms for me?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Vasseurth
  • 6,354
  • 12
  • 53
  • 81

7 Answers7

154

Rails 4+

class Like
  def after_initialize
    self.politics = false
  end
end

i = Like.new
i.politics #=> false

Rails 3.1 and below

class Like
  attr_accessor_with_default :politics, false
end

i = Like.new
i.politics #=> false

Pure Ruby

class Like
  attr_writer :politics
      
  def politics
    @politics || false
  end
end

i = Like.new
i.politics #=> false
Orlando
  • 9,374
  • 3
  • 56
  • 53
  • 19
    Note that the example only works for a default of false. I needed a default of true, so I used: `@politics.nil? ? true : @politics` – micapam Feb 11 '13 at 03:02
  • 3
    If you're defaulting to an array, use: `def politics; @politics ||= []; end` or << won't work until you assign a value to politics some other way. – A Fader Darkly Jul 17 '14 at 17:06
  • I think the `after_initialize` method suggested by Dave Newton is the best solution – josal Sep 12 '14 at 10:12
1

If you define your attr_accessor, by default the value is nil. You can write to it, thereby making it !nil

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
-1
class Song < ActiveRecord::Base
    def initialize(*args)
    super(*args)
      return unless self.new_record?
      self.play_count ||= 0
    end
end

In my opinion, I think this answer is good. Although we are overriding the initialize() method but since super is called on the first line of this method, it doesn't change anything to the base class initialize() method, rather this is a key feature of Object Oriented programming that we can override it, and add some more functionality at the time of initialization of objects. And also the initializer will not be skipped while reading objects from the database, since super is called on the first line of the function.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • 5
    IMO `after_initialize` is a better option than overriding a framework-overridden method, and the [Rails AR guide encourages its use](http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find). The issue is that AR might change from under you and change behavior. – Dave Newton May 22 '13 at 15:43
  • Thanks Dave por your suggestion, I think is the best one! – josal Sep 12 '14 at 10:14
-1

You could use the virtus gem:

https://github.com/solnic/virtus

From the README:

Virtus allows you to define attributes on classes, modules or class instances with optional information about types, reader/writer method visibility and coercion behavior. It supports a lot of coercions and advanced mapping of embedded objects and collections.

It specifically supports default values.

Thilo
  • 17,565
  • 5
  • 68
  • 84
-5

I've been using this form in ActiveRecord:

class Song < ActiveRecord::Base

    def initialize(*args)
      super(*args)
      return unless self.new_record?
      self.play_count ||= 0
    end
end
mcmoyer
  • 9
  • 3
  • 2
    You should not overwride initialize in ActiveRecord objects, use before_create instead. – tesserakt Jun 06 '12 at 13:52
  • why not? The initializer is skipped only when reading objects from the database. For a default value, you wouldn't want it overwriting info from the db anyway. – mcmoyer Jul 24 '12 at 18:54
  • @user1144360 Because as the [Rails AR guide notes](http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find) there's an `after_initialize` provided specifically to avoid the need to override `initialize`. IMO it's safer to do so over the long term. The issue is that AR might change from under you and change behavior. – Dave Newton May 22 '13 at 15:45
-6

This is not done in attr_accessor, rather, in your migration.

So .. you could perform a migration

(1) rails g migration ChangePoliticsColumnToDefaultValueFalse

(2) add this in def self.up

def self.up change_column :your_table, :politics, :boolean, :default => 0 end

The bottom line is that default attributes are set in migrations.

Hope this helps!

Edit:

There are some similar questions too that have been answered well:

Like here and here

Community
  • 1
  • 1
Benjamin Tan Wei Hao
  • 9,621
  • 3
  • 30
  • 56
-7

attr_accessor in rails are only virtual variable which is not store in database and it can be use only until active record not save or update in application. You can define attr_accessor in model like

class Contact < ActiveRecord::Base
attr_accessor :virtual_variable
end

and use in form like :-

 <div class="field">
    <%= f.label :virtual %><br>
    <%= f.text_field :virtual %>
  </div>

and you can found these vartual variable value in controller param...

Ganesh Shrivas
  • 157
  • 1
  • 2