lib/rom/sql/schema/associations_dsl.rb in rom-sql-1.0.0.beta3 vs lib/rom/sql/schema/associations_dsl.rb in rom-sql-1.0.0.rc1

- old
+ new

@@ -2,65 +2,183 @@ require 'rom/sql/association' module ROM module SQL class Schema < ROM::Schema + # Additional schema DSL for definition SQL associations + # + # This DSL is exposed in `associations do .. end` blocks in schema defintions. + # + # @api public class AssociationsDSL < BasicObject - attr_reader :source, :registry + # @!attribute [r] source + # @return [Relation::Name] The source relation + attr_reader :source + # @!attribute [r] registry + # @return [RelationRegistry] Relations registry from a rom container + attr_reader :registry + + # @api private def initialize(source, &block) @source = source @registry = {} instance_exec(&block) end + # Establish a one-to-many association + # + # @example using relation identifier + # has_many :tasks + # + # @example with a :through option + # # this establishes many-to-many association + # has_many :tasks, through: :users_tasks + # + # @example using aliased association with a custom view + # has_many :posts, as: :published_posts, view: :published + # + # @example using custom target relation + # has_many :user_posts, relation: :posts + # + # @param [Symbol] target The target relation identifier + # @param [Hash] options A hash with additional options + # + # @return [Associations::OneToMany] + # + # @see #many_to_many + # + # @api public def one_to_many(target, options = {}) if options[:through] many_to_many(target, options) else add(Association::OneToMany.new(source, target, options)) end end alias_method :has_many, :one_to_many + # Establish a one-to-one association + # + # @example using relation identifier + # one_to_one :addresses, as: :address + # + # @example with an intermediate join relation + # one_to_one :tasks, as: :priority_task, through: :assignments + # + # @param [Symbol] target The target relation identifier + # @param [Hash] options A hash with additional options + # + # @return [Associations::OneToOne] + # + # @see #belongs_to + # + # @api public def one_to_one(target, options = {}) if options[:through] one_to_one_through(target, options) else add(Association::OneToOne.new(source, target, options)) end end + # Establish a one-to-one association with a :through option + # + # @example + # one_to_one_through :users, as: :author, through: :users_posts + # + # @return [Associations::OneToOneThrough] + # + # @api public def one_to_one_through(target, options = {}) add(Association::OneToOneThrough.new(source, target, options)) end + # Establish a many-to-many association + # + # @example using relation identifier + # many_to_many :tasks, through: :users_tasks + # + # @param [Symbol] target The target relation identifier + # @param [Hash] options A hash with additional options + # + # @return [Associations::OneToOne] + # + # @see #one_to_many + # + # @api public def many_to_many(target, options = {}) add(Association::ManyToMany.new(source, target, options)) end + # Establish a many-to-one association + # + # @example using relation identifier + # many_to_one :users, as: :author + # + # @param [Symbol] target The target relation identifier + # @param [Hash] options A hash with additional options + # + # @return [Associations::OneToOne] + # + # @see #one_to_many + # + # @api public def many_to_one(target, options = {}) add(Association::ManyToOne.new(source, target, options)) end + # Shortcut for many_to_one which sets alias automatically + # + # @example with an alias (relation identifier is inferred via pluralization) + # belongs_to :user + # + # @example with an explicit alias + # belongs_to :users, as: :author + # + # @see #many_to_one + # + # @return [Associations::ManyToOne] + # + # @api public def belongs_to(name, options = {}) many_to_one(dataset_name(name), {as: name}.merge(options)) end + # Shortcut for one_to_one which sets alias automatically + # + # @example with an alias (relation identifier is inferred via pluralization) + # one_to_one :address + # + # @example with an explicit alias and a custom view + # one_to_one :posts, as: :priority_post, view: :prioritized + # + # @see #one_to_one + # + # @return [Associations::ManyToOne] + # + # @api public def has_one(name, options = {}) one_to_one(dataset_name(name), {as: name}.merge(options)) end + # Return an association set for a schema + # + # @return [AssociationSet] + # + # @api private def call AssociationSet.new(registry) end private + # @api private def add(association) registry[association.name] = association end + # @api private def dataset_name(name) ::Dry::Core::Inflector.pluralize(name).to_sym end end end