1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activerecord/test/models/developer.rb

358 lines
10 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "ostruct"
class Developer < ActiveRecord::Base
module TimestampAliases
extend ActiveSupport::Concern
included do
alias_attribute :created_at, :legacy_created_at
alias_attribute :updated_at, :legacy_updated_at
alias_attribute :created_on, :legacy_created_on
alias_attribute :updated_on, :legacy_updated_on
end
end
include TimestampAliases
module ProjectsAssociationExtension2
def find_least_recent
order("id ASC").first
end
end
self.ignored_columns = %w(first_name last_name)
has_and_belongs_to_many :projects do
def find_most_recent
order("id DESC").first
end
end
belongs_to :mentor
belongs_to :strict_loading_mentor, strict_loading: true, foreign_key: :mentor_id, class_name: "Mentor"
belongs_to :strict_loading_off_mentor, strict_loading: false, foreign_key: :mentor_id, class_name: "Mentor"
accepts_nested_attributes_for :projects
has_and_belongs_to_many :shared_computers, class_name: "Computer"
has_and_belongs_to_many :projects_extended_by_name,
-> { extending(ProjectsAssociationExtension) },
2016-08-06 13:37:57 -04:00
class_name: "Project",
join_table: "developers_projects",
association_foreign_key: "project_id"
has_and_belongs_to_many :projects_extended_by_name_twice,
-> { extending(ProjectsAssociationExtension, ProjectsAssociationExtension2) },
2016-08-06 13:37:57 -04:00
class_name: "Project",
join_table: "developers_projects",
association_foreign_key: "project_id"
has_and_belongs_to_many :projects_extended_by_name_and_block,
-> { extending(ProjectsAssociationExtension) },
2016-08-06 13:37:57 -04:00
class_name: "Project",
join_table: "developers_projects",
association_foreign_key: "project_id" do
def find_least_recent
order("id ASC").first
end
end
has_and_belongs_to_many :strict_loading_projects,
join_table: :developers_projects,
association_foreign_key: :project_id,
class_name: "Project",
strict_loading: true
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :special_projects, join_table: "developers_projects", association_foreign_key: "project_id"
has_and_belongs_to_many :sym_special_projects,
2016-08-06 13:37:57 -04:00
join_table: :developers_projects,
association_foreign_key: "project_id",
class_name: "SpecialProject"
has_many :audit_logs
has_many :required_audit_logs, class_name: "AuditLogRequired"
has_many :strict_loading_audit_logs, -> { strict_loading }, class_name: "AuditLog"
has_many :strict_loading_opt_audit_logs, strict_loading: true, class_name: "AuditLog"
has_many :contracts
2016-08-06 13:37:57 -04:00
has_many :firms, through: :contracts, source: :firm
has_many :comments, ->(developer) { where(body: "I'm #{developer.name}") }
has_many :ratings, through: :comments
has_one :ship, dependent: :nullify
has_one :strict_loading_ship, strict_loading: true, class_name: "Ship"
belongs_to :firm
has_many :contracted_projects, class_name: "Project"
2016-08-06 13:37:57 -04:00
scope :jamises, -> { where(name: "Jamis") }
2016-08-06 13:37:57 -04:00
validates_inclusion_of :salary, in: 50000..200000
validates_length_of :name, within: 3..20
before_create do |developer|
2016-08-06 13:37:57 -04:00
developer.audit_logs.build message: "Computer created"
end
attribute :last_name
def log=(message)
2016-08-06 13:37:57 -04:00
audit_logs.build message: message
end
after_find :track_instance_count
cattr_accessor :instance_count
def track_instance_count
self.class.instance_count ||= 0
self.class.instance_count += 1
end
private :track_instance_count
end
class SubDeveloper < Developer
end
class SpecialDeveloper < ActiveRecord::Base
self.table_name = "developers"
has_many :special_contracts, foreign_key: "developer_id"
end
class SymbolIgnoredDeveloper < ActiveRecord::Base
self.table_name = "developers"
self.ignored_columns = [:first_name, :last_name]
attribute :last_name
end
class AuditLog < ActiveRecord::Base
2016-08-06 13:37:57 -04:00
belongs_to :developer, validate: true
belongs_to :unvalidated_developer, class_name: "Developer"
end
class AuditLogRequired < ActiveRecord::Base
self.table_name = "audit_logs"
belongs_to :developer, required: true
end
class DeveloperWithBeforeDestroyRaise < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, join_table: "developers_projects", foreign_key: "developer_id"
before_destroy :raise_if_projects_empty!
def raise_if_projects_empty!
raise if projects.empty?
end
end
class DeveloperWithSelect < ActiveRecord::Base
self.table_name = "developers"
default_scope { select("name") }
end
Add option for `default_scope` to run on all queries This change allows for applications to optionally run a `default_scope` on `update` and `delete` queries. Default scopes already ran on select and insert queries. Applications can now run a set default scope on all queries for a model by setting a `all_queries` option: ```ruby class Article < ApplicationRecord default_scope -> { where(blog_id: 1) }, all_queries: true end ``` Using the default scope in this way is useful for applications that need to query by more than the primary key by default. An example of this would be in an application using a sharding strategy like Vitess like. For Rails sharding, we route connections first and then query the database. However, Vitess and other solutions use a parameter in the query to figure out how to route the queries. By extending `default_scope` to apply to all queries we can allow applications to optionally apply additional constraints to all queries. Note that this only works with `where` queries as it does not make sense to select a record by primary key with an order. With this change we're allowing apps to select with a primary key and an additional key. To make this change dynamic for routing queries in a tenant sharding strategy applications can use the `Current` API or parameters in a request to route queries: ```ruby class Article < ApplicationRecord default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true end ``` In order to achieve this I created a new object when default scopes are created. This allows us to store both the scope itself and whether we should run this on all queries. I chose not to implement an `on:` option that takes an array of actions because there is no simple or clear way to turn off the default scope for create/select. It also doesn't really make sense to only have a default scope for delete queries. The decision to use `all_queries` here allows for the implementation to be more flexible than it was without creating a mess in an application.
2020-11-19 17:20:45 -05:00
class DeveloperwithDefaultMentorScopeNot < ActiveRecord::Base
self.table_name = "developers"
default_scope -> { where(mentor_id: 1) }
end
class DeveloperWithDefaultMentorScopeAllQueries < ActiveRecord::Base
self.table_name = "developers"
default_scope -> { where(mentor_id: 1) }, all_queries: true
end
class DeveloperWithDefaultNilableMentorScopeAllQueries < ActiveRecord::Base
self.table_name = "developers"
firm_id = nil # Could be something like Current.mentor_id
default_scope -> { where(firm_id: firm_id) if firm_id }, all_queries: true
end
class DeveloperWithIncludes < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_many :audit_logs, foreign_key: :developer_id
default_scope { includes(:audit_logs) }
end
class DeveloperFilteredOnJoins < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
def self.default_scope
2016-08-06 13:37:57 -04:00
joins(:projects).where(projects: { name: "Active Controller" })
end
end
class DeveloperOrderedBySalary < ActiveRecord::Base
include Developer::TimestampAliases
self.table_name = "developers"
default_scope { order("salary DESC") }
scope :by_name, -> { order("name DESC") }
end
class DeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
default_scope { where("name = 'David'") }
end
class LazyLambdaDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope lambda { where(name: "David") }
end
class LazyBlockDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope { where(name: "David") }
end
class CallableDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope OpenStruct.new(call: where(name: "David"))
end
class ClassMethodDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
def self.default_scope
2016-08-06 13:37:57 -04:00
where(name: "David")
end
end
class ClassMethodReferencingScopeDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
scope :david, -> { where(name: "David") }
def self.default_scope
david
end
end
class LazyBlockReferencingScopeDeveloperCalledDavid < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
scope :david, -> { where(name: "David") }
default_scope { david }
end
class DeveloperCalledJamis < ActiveRecord::Base
include Developer::TimestampAliases
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope { where(name: "Jamis") }
scope :poor, -> { where("salary < 150000") }
scope :david, -> { where name: "David" }
scope :david2, -> { unscoped.where name: "David" }
end
class PoorDeveloperCalledJamis < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope -> { where(name: "Jamis", salary: 50000) }
end
class InheritedPoorDeveloperCalledJamis < DeveloperCalledJamis
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
default_scope -> { where(salary: 50000) }
end
class MultiplePoorDeveloperCalledJamis < ActiveRecord::Base
self.table_name = "developers"
default_scope { }
2016-08-06 13:37:57 -04:00
default_scope -> { where(name: "Jamis") }
default_scope -> { where(salary: 50000) }
end
module SalaryDefaultScope
extend ActiveSupport::Concern
2016-08-06 13:37:57 -04:00
included { default_scope { where(salary: 50000) } }
end
class ModuleIncludedPoorDeveloperCalledJamis < DeveloperCalledJamis
self.table_name = "developers"
include SalaryDefaultScope
end
2011-05-23 22:05:06 -04:00
class EagerDeveloperWithDefaultScope < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
2011-05-23 22:05:06 -04:00
default_scope { includes(:projects) }
2011-05-23 22:05:06 -04:00
end
class EagerDeveloperWithClassMethodDefaultScope < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
2011-05-23 22:05:06 -04:00
def self.default_scope
includes(:projects)
end
end
class EagerDeveloperWithLambdaDefaultScope < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
2011-05-23 22:05:06 -04:00
default_scope lambda { includes(:projects) }
end
class EagerDeveloperWithBlockDefaultScope < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
2011-05-23 22:05:06 -04:00
default_scope { includes(:projects) }
end
class EagerDeveloperWithCallableDefaultScope < ActiveRecord::Base
self.table_name = "developers"
2016-08-06 13:37:57 -04:00
has_and_belongs_to_many :projects, -> { order("projects.id") }, foreign_key: "developer_id", join_table: "developers_projects"
2011-05-23 22:05:06 -04:00
2016-08-06 13:37:57 -04:00
default_scope OpenStruct.new(call: includes(:projects))
2011-05-23 22:05:06 -04:00
end
class ThreadsafeDeveloper < ActiveRecord::Base
self.table_name = "developers"
def self.default_scope
2017-01-01 13:34:17 -05:00
Thread.current[:default_scope_delay].call
limit(1)
end
end
class CachedDeveloper < ActiveRecord::Base
include Developer::TimestampAliases
self.table_name = "developers"
self.cache_timestamp_format = :number
end
class DeveloperWithIncorrectlyOrderedHasManyThrough < ActiveRecord::Base
self.table_name = "developers"
has_many :companies, through: :contracts
has_many :contracts, foreign_key: :developer_id
end
class DeveloperName < ActiveRecord::Type::String
def deserialize(value)
"Developer: #{value}"
end
end
class AttributedDeveloper < ActiveRecord::Base
self.table_name = "developers"
attribute :name, DeveloperName.new
self.ignored_columns += ["name"]
end
class ColumnNamesCachedDeveloper < ActiveRecord::Base
self.table_name = "developers"
self.ignored_columns += ["name"] if column_names.include?("name")
end