Working with Active Record

Published: by Creative Commons Licence

Basic

  • Class Name 對應 Database Table name
  • 預設的 primary key 是 "id"
  • 繼承 ActiveRecord::Base
class Client < ActiveRecord::Base
end

Relationship

  • model之間的關聯之一 :has_many
class Client < ActiveRecord::Base
	has_many :billing_codes
	has_many :billable_weeks
	has_many :timesheets, through: :billable_weeks
end

Setting Names Manually

  • 自訂對應的 SQL table name 及 primary key
class Client < ActiveRecord::Base
	self.table_name = "CLIENT"
	self.primary_key = "CLIENT_ID"
end
  • 從application層級,修改所有model的對應table名稱 for legacy naming schemes in config/application.rb:
# turn off table pluralization
config.active_record.pluralize_table_names = false

# default primary key is set to "tableid"
config.active_record.primary_key_prefix_type = :table_name

# default primary key is set to "table_id"
config.active_record.primary_key_prefix_type = :table_name_with_underscore

# ???
config.active_record.table_name_prefix = ???

# ???
config.active_record.table_name_suffix = ???

default attribute value

  • 自訂預設值
# default value of category is 'n/a' instead of nil
class TimesheetEntry < ActiveRecord::Base
	def category
		read_attribute(:category) || 'n/a'
	end
end

ActiveRecord::Store

??? not understand

CRUD

create

>> c = Client.new
=> #<Client id: nil, name: nil, code: nil>
>> c.new_record?
=> true
>> c.persisted?
=> false
>> c = Client.new do |client|
?> client.name = "PC"
>> client.code = "AP"
>> end
=> #<Client id: 1, name: "PC", code: "AP">
>> c = Client.create(name: "PC", code: "AP")
=> #<Client id: 1, name: "PC", code: "AP">

read

reading objects

Project.find(1)
Client.all
Product.last
Product.find([1, 2])

reading and writing attributes

# dot notation
client.name
client.code
# hash notation
client[:name]
client['name']

override the accessor

class Client < ActiveRecord::Base
	def name
		read_attribute(:name).reverse
		# self.name.reverse => cause recursive call! don't use it!
	end
end
first_name.name
class Project < ActiveRecord::Base
	# description can not be changed to blank string.
	def description=(new_value)
		write_attribute(:description, new_value) unless new_value.blank?
	end
end

attributes method

# show all attributes
# only value of read_attribute
# no custom attribute reader
first_client.attributes

custom SQL queries

Client.find_by_sql("select * from clients")

query cache

User.cache do
	User.first
	User.first
	User.first
end

update

class ProjectController < ApplicationController
	def update
		project = Project.find(params[:id])
		if project.update(params[:project])
			redirect_to project
		else
			render 'edit'
		end
	end
end
# 1st parameter: update value or update sql query
# 2nd parameter: where clause
Project.update_all({manager: 'PC'}, technology: 'Rails'}
Project.update_all("cost = cost * 3", "lower(technology) LIKE '%microsoft%'")

touching records (update timestamp attribute)

>> user = User.first
>> user.touch # sets updated_at to now
>> user.touch(:viewed_at) # set viewed_at and updated_at to now

If a :touch option is provided to a belongs_to relation, it will touch the parent record when the child is touched.

>> user.touch # also calls user.client.touch

readonly attributes

class Customer < ActiveRecord::Base
	attr_readonly :social_security_number
end
>> Customer.readonly_attributes

delete, destroying

The delete method executes a SQL statement to remove the object's data from the database.

bad_timesheet.delete

The destroy method will both remove the object from the database and prevent you from modifying it again

bad_timesheet.destroy