diff --git a/docs/getting_started.md b/docs/getting_started.md index b86df9cf..8d75bc92 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -83,7 +83,7 @@ end This will override the default primary key of `id : Int64`. -#### Natural Keys +### Natural Keys For natural keys, you can set `auto: false` option to disable auto increment. @@ -95,7 +95,7 @@ class Site < Granite::Base end ``` -#### UUIDs +### UUIDs For databases that utilize UUIDs as the primary key, the `primary` macro can be used again with the `auto: false` option. A `before_create` callback can be added to the model to randomly generate and set a secure UUID on the record before it is saved to the database. @@ -114,6 +114,12 @@ class Book < Granite::Base end ``` +### Generating Documentation +By default, running `crystal docs` will **not** include Granite methods, constants, and properties. To include these, have an ENV variable: `DISABLE_GRANITE_DOCS=false` set before running `crystal docs`. -See the [Docs folder](./) for additional information. \ No newline at end of file +The `field` and `primary` macros have a comment option that will specify the documentation comment to apply to that property's getter and setter. + +`field age : Int32, comment: "# Number of seconds since the post was posted"` + +See the [Docs folder](./) for additional information. diff --git a/src/granite/callbacks.cr b/src/granite/callbacks.cr index e7a89feb..645b903b 100644 --- a/src/granite/callbacks.cr +++ b/src/granite/callbacks.cr @@ -10,13 +10,13 @@ module Granite::Callbacks macro included macro inherited - CALLBACKS = { + disable_granite_docs? CALLBACKS = { {% for name in CALLBACK_NAMES %} {{name.id}}: [] of Nil, {% end %} } {% for name in CALLBACK_NAMES %} - def {{name.id}} + disable_granite_docs? def {{name.id}} __{{name.id}} end {% end %} diff --git a/src/granite/fields.cr b/src/granite/fields.cr index ed9590da..26771de8 100644 --- a/src/granite/fields.cr +++ b/src/granite/fields.cr @@ -6,8 +6,8 @@ module Granite::Fields macro included macro inherited - CONTENT_FIELDS = {} of Nil => Nil - FIELDS = {} of Nil => Nil + disable_granite_docs? CONTENT_FIELDS = {} of Nil => Nil + disable_granite_docs? FIELDS = {} of Nil => Nil end end @@ -36,6 +36,7 @@ module Granite::Fields {% end %} # Create the properties + {% for name, options in FIELDS %} {% type = options[:type] %} {% suffixes = options[:raise_on_nil] ? ["?", ""] : ["", "!"] %} @@ -45,24 +46,27 @@ module Granite::Fields {% if options[:yaml_options] %} @[YAML::Field({{**options[:yaml_options]}})] {% end %} + {% if options[:comment] %} + {{options[:comment].id}} + {% end %} property{{suffixes[0].id}} {{name.id}} : Union({{type.id}} | Nil) - def {{name.id}}{{suffixes[1].id}} + disable_granite_docs? def {{name.id}}{{suffixes[1].id}} raise {{@type.name.stringify}} + "#" + {{name.stringify}} + " cannot be nil" if @{{name.id}}.nil? @{{name.id}}.not_nil! end {% end %} # keep a hash of the fields to be used for mapping - def self.fields : Array(String) + disable_granite_docs? def self.fields : Array(String) @@fields ||= {{ FIELDS.empty? ? "[] of String".id : FIELDS.keys.map(&.id.stringify) }} end - def self.content_fields : Array(String) + disable_granite_docs? def self.content_fields : Array(String) @@content_fields ||= {{ CONTENT_FIELDS.empty? ? "[] of String".id : CONTENT_FIELDS.keys.map(&.id.stringify) }} end # keep a hash of the params that will be passed to the adapter. - def content_values + disable_granite_docs? def content_values parsed_params = [] of DB::Any {% for name, options in CONTENT_FIELDS %} parsed_params << {{name.id}} @@ -70,7 +74,7 @@ module Granite::Fields return parsed_params end - def to_h + disable_granite_docs? def to_h fields = {} of String => DB::Any {% for name, options in FIELDS %} @@ -87,7 +91,7 @@ module Granite::Fields return fields end - def read_attribute(attribute_name : Symbol | String) : DB::Any + disable_granite_docs? def read_attribute(attribute_name : Symbol | String) : DB::Any {% begin %} case attribute_name.to_s {% for name, options in FIELDS %} @@ -99,13 +103,13 @@ module Granite::Fields {% end %} end - def set_attributes(args : Hash(String | Symbol, Type)) + disable_granite_docs? def set_attributes(args : Hash(String | Symbol, Type)) args.each do |k, v| cast_to_field(k, v.as(Type)) end end - def set_attributes(**args) + disable_granite_docs? def set_attributes(**args) set_attributes(args.to_h) end diff --git a/src/granite/migrator.cr b/src/granite/migrator.cr index 208bf9af..4e71dab0 100644 --- a/src/granite/migrator.cr +++ b/src/granite/migrator.cr @@ -42,7 +42,7 @@ module Granite::Migrator {% klass = @type.name %} {% adapter = "#{klass}.adapter".id %} - class Migrator < Granite::Migrator::Base + disable_granite_docs? class Migrator < Granite::Migrator::Base def drop {{klass}}.exec "DROP TABLE IF EXISTS #{ @quoted_table_name };" end @@ -85,7 +85,7 @@ module Granite::Migrator end end - def self.migrator(**args) + disable_granite_docs? def self.migrator(**args) Migrator.new(self, **args) end end diff --git a/src/granite/querying.cr b/src/granite/querying.cr index e4fe6020..5186082c 100644 --- a/src/granite/querying.cr +++ b/src/granite/querying.cr @@ -8,13 +8,13 @@ module Granite::Querying \{% primary_type = PRIMARY[:type] %} # Create the from_sql method - def self.from_sql(result) + disable_granite_docs? def self.from_sql(result) model = \{{@type.name.id}}.new model.set_attributes(result) model end - def set_attributes(result : DB::ResultSet) + disable_granite_docs? def set_attributes(result : DB::ResultSet) # Loading from DB means existing records. @new_record = false \{% for name, options in FIELDS %} diff --git a/src/granite/table.cr b/src/granite/table.cr index 2fe4f150..4ee1575d 100644 --- a/src/granite/table.cr +++ b/src/granite/table.cr @@ -1,8 +1,18 @@ +# Adds a :nodoc: to granite methods/constants if `DISABLE_GRANTE_DOCS` ENV var is true +macro disable_granite_docs?(stmt) + {% unless env("DISABLE_GRANITE_DOCS") == "false" %} + # :nodoc: + {{stmt.id}} + {% else %} + {{stmt.id}} + {% end %} +end + module Granite::Table macro included macro inherited - SETTINGS = {} of Nil => Nil - PRIMARY = {name: id, type: Int64, auto: true} + disable_granite_docs? SETTINGS = {} of Nil => Nil + disable_granite_docs? PRIMARY = {name: id, type: Int64, auto: true} end end @@ -11,7 +21,7 @@ module Granite::Table macro adapter(name) @@adapter = Granite::Adapter::{{name.id.capitalize}}.new("{{name.id}}") - def self.adapter + disable_granite_docs? def self.adapter @@adapter end end @@ -27,6 +37,13 @@ module Granite::Table {% PRIMARY[:type] = decl.type %} end + # specify the primary key column and type and comment + macro primary(decl, comment) + {% PRIMARY[:name] = decl.var %} + {% PRIMARY[:type] = decl.type %} + {% PRIMARY[:comment] = comment %} + end + # specify the primary key column and type and auto_increment macro primary(decl, auto) {% PRIMARY[:name] = decl.var %} @@ -34,6 +51,14 @@ module Granite::Table {% PRIMARY[:auto] = auto %} end + # specify the primary key column and type and auto_increment and comment + macro primary(decl, comment, auto) + {% PRIMARY[:name] = decl.var %} + {% PRIMARY[:type] = decl.type %} + {% PRIMARY[:auto] = auto %} + {% PRIMARY[:comment] = comment %} + end + macro __process_table {% name_space = @type.name.gsub(/::/, "_").underscore.id %} {% table_name = SETTINGS[:table_name] || name_space + "s" %} @@ -46,27 +71,27 @@ module Granite::Table @@primary_auto = "{{primary_auto}}" @@primary_type = "{{primary_type}}" - def self.table_name + disable_granite_docs? def self.table_name @@table_name end - def self.primary_name + disable_granite_docs? def self.primary_name @@primary_name end - def self.primary_type + disable_granite_docs? def self.primary_type @@primary_type end - def self.primary_auto + disable_granite_docs? def self.primary_auto @@primary_auto end - def self.quoted_table_name + disable_granite_docs? def self.quoted_table_name @@adapter.quote(table_name) end - def self.quote(column_name) + disable_granite_docs? def self.quote(column_name) @@adapter.quote(column_name) end end diff --git a/src/granite/transactions.cr b/src/granite/transactions.cr index c1c54af5..88772b80 100644 --- a/src/granite/transactions.cr +++ b/src/granite/transactions.cr @@ -2,22 +2,22 @@ require "./exceptions" module Granite::Transactions module ClassMethods - def create(**args) + disable_granite_docs? def create(**args) create(args.to_h) end - def create(args : Hash(Symbol | String, DB::Any)) + disable_granite_docs? def create(args : Hash(Symbol | String, DB::Any)) instance = new instance.set_attributes(args) instance.save instance end - def create!(**args) + disable_granite_docs? def create!(**args) create!(args.to_h) end - def create!(args : Hash(Symbol | String, DB::Any)) + disable_granite_docs? def create!(args : Hash(Symbol | String, DB::Any)) instance = create(args) if instance.errors.any? @@ -39,7 +39,7 @@ module Granite::Transactions # The import class method will run a batch INSERT statement for each model in the array # the array must contain only one model class # invalid model records will be skipped - def self.import(model_array : Array(self) | Granite::Collection(self), batch_size : Int32 = model_array.size) + disable_granite_docs? def self.import(model_array : Array(self) | Granite::Collection(self), batch_size : Int32 = model_array.size) begin fields_duplicate = fields.dup model_array.each_slice(batch_size, true) do |slice| @@ -50,7 +50,7 @@ module Granite::Transactions end end - def self.import(model_array : Array(self) | Granite::Collection(self), update_on_duplicate : Bool, columns : Array(String), batch_size : Int32 = model_array.size) + disable_granite_docs? def self.import(model_array : Array(self) | Granite::Collection(self), update_on_duplicate : Bool, columns : Array(String), batch_size : Int32 = model_array.size) begin fields_duplicate = fields.dup model_array.each_slice(batch_size, true) do |slice| @@ -61,7 +61,7 @@ module Granite::Transactions end end - def self.import(model_array : Array(self) | Granite::Collection(self), ignore_on_duplicate : Bool, batch_size : Int32 = model_array.size) + disable_granite_docs? def self.import(model_array : Array(self) | Granite::Collection(self), ignore_on_duplicate : Bool, batch_size : Int32 = model_array.size) begin fields_duplicate = fields.dup model_array.each_slice(batch_size, true) do |slice| @@ -72,7 +72,7 @@ module Granite::Transactions end end - def set_timestamps(*, to time = Time.now, mode = :create) + disable_granite_docs? def set_timestamps(*, to time = Time.now, mode = :create) if mode == :create @created_at = time.to_utc.at_beginning_of_second end @@ -132,7 +132,7 @@ module Granite::Transactions # The save method will check to see if the primary exists yet. If it does it # will call the update method, otherwise it will call the create method. # This will update the timestamps appropriately. - def save + disable_granite_docs? def save return false unless valid? begin @@ -158,32 +158,32 @@ module Granite::Transactions end - def save! + disable_granite_docs? def save! save || raise Granite::RecordNotSaved.new(self.class.name, self) end - def update(**args) + disable_granite_docs? def update(**args) update(args.to_h) end - def update(args : Hash(Symbol | String, DB::Any)) + disable_granite_docs? def update(args : Hash(Symbol | String, DB::Any)) set_attributes(args) save end - def update!(**args) + disable_granite_docs? def update!(**args) update!(args.to_h) end - def update!(args : Hash(Symbol | String, DB::Any)) + disable_granite_docs? def update!(args : Hash(Symbol | String, DB::Any)) set_attributes(args) save! end # Destroy will remove this from the database. - def destroy + disable_granite_docs? def destroy begin __before_destroy __destroy @@ -198,7 +198,7 @@ module Granite::Transactions true end - def destroy! + disable_granite_docs? def destroy! destroy || raise Granite::RecordNotDestroyed.new(self.class.name, self) end end @@ -214,7 +214,7 @@ module Granite::Transactions getter? destroyed : Bool = false # Returns true if the record is persisted. - def persisted? + disable_granite_docs? def persisted? !(new_record? || destroyed?) end end diff --git a/src/granite/validators.cr b/src/granite/validators.cr index 166867ba..059b1f74 100644 --- a/src/granite/validators.cr +++ b/src/granite/validators.cr @@ -24,19 +24,19 @@ module Granite::Validators macro inherited @@validators = Array({field: String, message: String, block: Proc(self, Bool)}).new - def self.validate(message : String, &block : self -> Bool) + disable_granite_docs? def self.validate(message : String, &block : self -> Bool) self.validate(:base, message, block) end - def self.validate(field : (Symbol | String), message : String, &block : self -> Bool) + disable_granite_docs? def self.validate(field : (Symbol | String), message : String, &block : self -> Bool) self.validate(field, message, block) end - def self.validate(message : String, block : self -> Bool) + disable_granite_docs? def self.validate(message : String, block : self -> Bool) self.validate(:base, message, block) end - def self.validate(field : (Symbol | String), message : String, block : self -> Bool) + disable_granite_docs? def self.validate(field : (Symbol | String), message : String, block : self -> Bool) @@validators << {field: field.to_s, message: message, block: block} end end