Rails: create objects with `has_one` relation and skip validation

I encountered with this situation today;

I have `spree_user` object which can have one `bill_address` but bill address has one filed called `zipcode` field which is required and needs to be valid but I might not always have valid data for that field.

So needed to skip the validation for create method. Found that its not possible to skip validation using `create` method.  Continue reading

Passing Modifiers :: rails generate migration

2.3 Passing Modifiers

Some commonly used type modifiers can be passed directly on the command line. They are enclosed by curly braces and follow the field type:

For instance, running:

$ bin/rails generate migration AddDetailsToProducts 'price:decimal{5,2}' supplier:references{polymorphic}

will produce a migration that looks like this

class AddDetailsToProducts < ActiveRecord::Migration
  def change
    add_column :products, :price, :decimal, precision: 5, scale: 2
    add_reference :products, :supplier, polymorphic: true, index: true
  end
end

Have a look at the generators help output for further details.

Advanced usage

Sometimes you have to automatically add index for columns in your migration. It’s not a problem:

$ rails g model user email:index location_id:integer:index

Or uniq index:

$ rails g model user pseudo:string:uniq

Set limit for field of integer, string, text and binary fields:

$ rails generate model user pseudo:string{30}

Special syntax to generate decimal field with scale and precision:

$ rails generate model product 'price:decimal{10,2}'

Pay attention that you have to wrap parameter price:decimal{10,2} to quotes. It’s vital and you may have incorrect behavior of generator if you don’t do it. Full explanation of this case is here.

You can combine any single curly brace option with the index options:

$ rails generate model user username:string{30}:uniq

And the last useful feature of generators – it’s options to generate reference columns (fields which are used in rails as foreign keys):

$ rails generate model photo album:references

This command will generate photos table with integer field album_id and also it will add index for this field automatically. Make sure in it by looking at generated migration:

class CreatePhotos < ActiveRecord::Migration
  def change
    create_table :photos do |t|
      t.references :album

      t.timestamps
    end
    add_index :photos, :album_id
  end
end

For polymorphic reference use this syntax:

$ rails generate model product supplier:references{polymorphic}

Polymorphic reference with indexes:

$ rails generate model product supplier:references{polymorphic}:index

 Sources

http://railsguides.net/advanced-rails-model-generators/

Rails : ActiveRecord : Enum

Active Record’s enum makes your life alot easier. If you need to maintain status/state of any activerecord object this feature could be great help.

Declare an enum attribute where the values map to integers in the database, but can be queried by name.

Example:

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.update! status: 1
conversation.status = "archived"

# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

Sources

http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html

Different between update, update_columns, update_column, update_attributes, assign_attributes

update(id, attributes) public

Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.

Parameters

  • id – This should be the id or an array of ids to be updated.
  • attributes – This should be a hash of attributes to be set on the object, or an array of hashes.
     # Updating one record:
      Person.update(15, :user_name => 'Samuel', :group => 'expert')
    
      # Updating multiple records:
      people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
      Person.update(people.keys, people.values)

update_columns(attributes) public

Updates the attributes directly in the database issuing an UPDATE SQL statement and sets them in the receiver:

user.update_columns(last_request_at: Time.current)

This is the fastest way to update attributes because it goes straight to the database, but take into account that in consequence the regular update procedures are totally bypassed. In particular:

This method raises an +ActiveRecord::ActiveRecordError+ when called on new objects, or when at least one of the attributes is marked as readonly


update_column(name, value) public

Equivalent to update_columns(name => value).


update_attributes(attributes) public

Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will fail and false will be returned.


assign_attributes(new_attributes, options = {}) public

Allows you to set all the attributes for a particular mass-assignment security role by passing in a hash ofattributes with keys matching the attribute names (which again matches the column names) and the role name using the :as option.

To bypass mass-assignment security you can use the :without_protection => true option.

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true })
user.name       # => "Josh"
user.is_admin?  # => false

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
user.name       # => "Josh"
user.is_admin?  # => true

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
user.name       # => "Josh"
user.is_admin?  # => true

Source: http://apidock.com/rails/ActiveRecord