There was a problem expanding macro 'common_mapping'
wJoenn opened this issue · 2 comments
Context
I just started a small CRUD app which currently has a single model
# src/models/task.cr
class Task < Jennifer::Model::Base
with_timestamps
mapping(
id: Primary32,
title: String,
completed: { type: Bool, default: false },
created_at: Time?,
updated_at: Time?,
)
end
which is being required by my config file
# config/config.cr
require "./initializers/**"
require "../src/models/*"
and the only initializer I currently have is jennifer
's
# config/initializers/database.cr
require "jennifer"
require "jennifer/adapter/postgres"
APP_ENV = ENV["KEMAL_ENV"]? || "development"
Jennifer::Config.configure do |conf|
conf.read("config/database.yml", APP_ENV)
conf.from_uri(ENV["DATABASE_URI"]) if ENV.has_key?("DATABASE_URI")
end
Log.setup "db", :debug, Log::IOBackend.new(formatter: Jennifer::Adapter::DBFormatter)
Issue
Anytime I require the config
file I get a long log of error in my terminal.
The notable errors are
There was a problem expanding macro 'common_mapping'
Called macro defined in lib/jennifer/src/jennifer/model/common_mapping.cr:5:5
Warning: positional parameter 'pull' corresponds to parameter 'values' of the overridden method Jennifer::Model::Base::AbstractClassMethods#new(values : Hash | NamedTuple), which has a different name and may affect named argument passing
Here is the full log
There was a problem expanding macro 'base_mapping'
Called macro defined in lib/jennifer/src/jennifer/model/mapping.cr:206:7
206 | macro base_mapping(strict = true)
Which expanded to:
-> 1 | common_mapping(true) 2 | 3 | 4 | 5 | # :nodoc: 6 | WITH_DEFAULT_CONSTRUCTOR = false 7 | 8 | # :nodoc: 9 | def self.primary_auto_incrementable? 10 | true 11 | end 12 | 13 | 14 | 15 | def destroy : Bool 16 | return false if new_record? 17 | 18 | result = 19 | if self.class.write_adapter.under_transaction? 20 | destroy_without_transaction 21 | else 22 | self.class.transaction { destroy_without_transaction } 23 | end 24 | return false unless result 25 | 26 | self.class.write_adapter.subscribe_on_commit(->__after_destroy_commit_callback) if HAS_DESTROY_COMMIT_CALLBACK 27 | self.class.write_adapter.subscribe_on_rollback(->__after_destroy_rollback_callback) if HAS_DESTROY_ROLLBACK_CALLBACK 28 | true 29 | end 30 | 31 | # :nodoc: 32 | def changed? : Bool 33 | 34 | @id_changed || 35 | 36 | @title_changed || 37 | 38 | @completed_changed || 39 | 40 | @created_at_changed || 41 | 42 | @updated_at_changed || 43 | 44 | false 45 | end 46 | 47 | # :nodoc: 48 | def update_columns(values : Hash(String | Symbol, AttrType)) 49 | values.each do |name, value| 50 | case name.to_s 51 | 52 | 53 | when "id" 54 | if value.is_a?(Int32?) 55 | @id = value.as(Int32?) 56 | @id_changed = true 57 | else 58 | raise ::Jennifer::BaseException.new("Wrong type for #{self.class}##{name} : #{value.class}") 59 | end 60 | 61 | 62 | 63 | when "title" 64 | if value.is_a?(String) 65 | @title = value.as(String) 66 | @title_changed = true 67 | else 68 | raise ::Jennifer::BaseException.new("Wrong type for #{self.class}##{name} : #{value.class}") 69 | end 70 | 71 | 72 | 73 | when "completed" 74 | if value.is_a?(Bool) 75 | @completed = value.as(Bool) 76 | @completed_changed = true 77 | else 78 | raise ::Jennifer::BaseException.new("Wrong type for #{self.class}##{name} : #{value.class}") 79 | end 80 | 81 | 82 | 83 | when "created_at" 84 | if value.is_a?(::Union(Time, ::Nil)) 85 | @created_at = value.as(::Union(Time, ::Nil)) 86 | @created_at_changed = true 87 | else 88 | raise ::Jennifer::BaseException.new("Wrong type for #{self.class}##{name} : #{value.class}") 89 | end 90 | 91 | 92 | 93 | when "updated_at" 94 | if value.is_a?(::Union(Time, ::Nil)) 95 | @updated_at = value.as(::Union(Time, ::Nil)) 96 | @updated_at_changed = true 97 | else 98 | raise ::Jennifer::BaseException.new("Wrong type for #{self.class}##{name} : #{value.class}") 99 | end 100 | 101 | 102 | else 103 | raise ::Jennifer::UnknownAttribute.new(name, self.class) 104 | end 105 | end 106 | 107 | self.class.write_adapter.update(self) 108 | __refresh_changes 109 | end 110 | 111 | # :nodoc: 112 | def set_attribute(name : String | Symbol, value : AttrType) 113 | case name.to_s 114 | 115 | 116 | when "id" 117 | if value.is_a?(Int32?) || value.is_a?(String) 118 | self.id = value 119 | else 120 | raise ::Jennifer::BaseException.new("wrong type for #{name} : #{value.class}") 121 | end 122 | 123 | 124 | 125 | when "title" 126 | if value.is_a?(String) || value.is_a?(String) 127 | self.title = value 128 | else 129 | raise ::Jennifer::BaseException.new("wrong type for #{name} : #{value.class}") 130 | end 131 | 132 | 133 | 134 | when "completed" 135 | if value.is_a?(Bool) || value.is_a?(String) 136 | self.completed = value 137 | else 138 | raise ::Jennifer::BaseException.new("wrong type for #{name} : #{value.class}") 139 | end 140 | 141 | 142 | 143 | when "created_at" 144 | if value.is_a?(::Union(Time, ::Nil)) || value.is_a?(String) 145 | self.created_at = value 146 | else 147 | raise ::Jennifer::BaseException.new("wrong type for #{name} : #{value.class}") 148 | end 149 | 150 | 151 | 152 | when "updated_at" 153 | if value.is_a?(::Union(Time, ::Nil)) || value.is_a?(String) 154 | self.updated_at = value 155 | else 156 | raise ::Jennifer::BaseException.new("wrong type for #{name} : #{value.class}") 157 | end 158 | 159 | 160 | else 161 | raise ::Jennifer::UnknownAttribute.new(name, self.class) 162 | end 163 | end 164 | 165 | # :nodoc: 166 | def arguments_to_save 167 | hash = changes 168 | {args: hash.values, fields: hash.keys} 169 | end 170 | 171 | # :nodoc: 172 | def arguments_to_insert 173 | args = [] of ::Jennifer::DBAny 174 | fields = [] of String 175 | 176 | 177 | 178 | 179 | args << attribute_before_typecast("title") 180 | fields << "title" 181 | 182 | 183 | 184 | args << attribute_before_typecast("completed") 185 | fields << "completed" 186 | 187 | 188 | 189 | args << attribute_before_typecast("created_at") 190 | fields << "created_at" 191 | 192 | 193 | 194 | args << attribute_before_typecast("updated_at") 195 | fields << "updated_at" 196 | 197 | 198 | {args: args, fields: fields} 199 | end 200 | 201 | # :nodoc: 202 | def changes : Hash(String, ::Jennifer::DBAny) 203 | hash = Hash(String, ::Jennifer::DBAny).new 204 | 205 | 206 | 207 | 208 | 209 | 210 | hash["title"] = attribute_before_typecast("title") if @title_changed 211 | 212 | 213 | 214 | 215 | hash["completed"] = attribute_before_typecast("completed") if @completed_changed 216 | 217 | 218 | 219 | 220 | hash["created_at"] = attribute_before_typecast("created_at") if @created_at_changed 221 | 222 | 223 | 224 | 225 | hash["updated_at"] = attribute_before_typecast("updated_at") if @updated_at_changed 226 | 227 | 228 | hash 229 | end 230 | 231 | # Extracts arguments due to mapping from *pull* and returns tuple for fields assignment. 232 | # It stands on that fact result set has all defined fields in a row 233 | # NOTE: don't use it manually - there is some dependencies on caller such as reading result set to the end 234 | # if exception was raised 235 | private def _extract_attributes(pull : DB::ResultSet) 236 | requested_columns_count = self.class.actual_table_field_count 237 | ::Jennifer::BaseException.assert_column_count(requested_columns_count, pull.column_count) 238 | 239 | __temp_116 = nil 240 | __temp_117 = false 241 | 242 | __temp_118 = nil 243 | __temp_119 = false 244 | 245 | __temp_120 = false 246 | __temp_121 = false 247 | 248 | __temp_122 = nil 249 | __temp_123 = false 250 | 251 | __temp_124 = nil 252 | __temp_125 = false 253 | 254 | requested_columns_count.times do 255 | column = pull.column_name(pull.column_index) 256 | case column 257 | 258 | 259 | when "id" 260 | __temp_117 = true 261 | begin 262 | __temp_116 = 263 | 264 | pull.read(Int32?) 265 | 266 | rescue e : Exception 267 | raise ::Jennifer::DataTypeMismatch.build(column, Task, e) 268 | end 269 | 270 | 271 | when "title" 272 | __temp_119 = true 273 | begin 274 | __temp_118 = 275 | 276 | pull.read(String) 277 | 278 | rescue e : Exception 279 | raise ::Jennifer::DataTypeMismatch.build(column, Task, e) 280 | end 281 | 282 | 283 | when "completed" 284 | __temp_121 = true 285 | begin 286 | __temp_120 = 287 | 288 | pull.read(Bool) 289 | 290 | rescue e : Exception 291 | raise ::Jennifer::DataTypeMismatch.build(column, Task, e) 292 | end 293 | 294 | 295 | when "created_at" 296 | __temp_123 = true 297 | begin 298 | __temp_122 = 299 | 300 | Jennifer::Model::TimeZoneConverter.from_db(pull, self.class.columns_tuple[:created_at]) 301 | 302 | rescue e : Exception 303 | raise ::Jennifer::DataTypeMismatch.build(column, Task, e) 304 | end 305 | 306 | 307 | when "updated_at" 308 | __temp_125 = true 309 | begin 310 | __temp_124 = 311 | 312 | Jennifer::Model::TimeZoneConverter.from_db(pull, self.class.columns_tuple[:updated_at]) 313 | 314 | rescue e : Exception 315 | raise ::Jennifer::DataTypeMismatch.build(column, Task, e) 316 | end 317 | 318 | else 319 | 320 | raise ::Jennifer::BaseException.new("Undefined column #{column} for model Task.") 321 | 322 | end 323 | end 324 | 325 | 326 | unless __temp_117 327 | raise ::Jennifer::BaseException.new("Column Task.id hasn't been found in the result set.") 328 | end 329 | 330 | unless __temp_119 331 | raise ::Jennifer::BaseException.new("Column Task.title hasn't been found in the result set.") 332 | end 333 | 334 | unless __temp_121 335 | raise ::Jennifer::BaseException.new("Column Task.completed hasn't been found in the result set.") 336 | end 337 | 338 | unless __temp_123 339 | raise ::Jennifer::BaseException.new("Column Task.created_at hasn't been found in the result set.") 340 | end 341 | 342 | unless __temp_125 343 | raise ::Jennifer::BaseException.new("Column Task.updated_at hasn't been found in the result set.") 344 | end 345 | 346 | 347 | 348 | { 349 | 350 | begin 351 | __temp_116.as(Int32?) 352 | rescue e : Exception 353 | raise ::Jennifer::DataTypeCasting.build("id", Task, e) 354 | end, 355 | 356 | begin 357 | __temp_118.as(String) 358 | rescue e : Exception 359 | raise ::Jennifer::DataTypeCasting.build("title", Task, e) 360 | end, 361 | 362 | begin 363 | __temp_120.as(Bool) 364 | rescue e : Exception 365 | raise ::Jennifer::DataTypeCasting.build("completed", Task, e) 366 | end, 367 | 368 | begin 369 | __temp_122.as(::Union(Time, ::Nil)) 370 | rescue e : Exception 371 | raise ::Jennifer::DataTypeCasting.build("created_at", Task, e) 372 | end, 373 | 374 | begin 375 | __temp_124.as(::Union(Time, ::Nil)) 376 | rescue e : Exception 377 | raise ::Jennifer::DataTypeCasting.build("updated_at", Task, e) 378 | end, 379 | 380 | } 381 | 382 | end 383 | 384 | private def _extract_attributes(values : Hash(String, AttrType)) 385 | 386 | __temp_116 = nil 387 | 388 | 389 | if values.has_key?("id") 390 | __temp_116 = 391 | 392 | values["id"] 393 | 394 | elsif values.has_key?("id") 395 | __temp_116 = 396 | 397 | values["id"] 398 | 399 | end 400 | 401 | __temp_118 = nil 402 | 403 | 404 | if values.has_key?("title") 405 | __temp_118 = 406 | 407 | values["title"] 408 | 409 | elsif values.has_key?("title") 410 | __temp_118 = 411 | 412 | values["title"] 413 | 414 | end 415 | 416 | __temp_120 = false 417 | 418 | 419 | if values.has_key?("completed") 420 | __temp_120 = 421 | 422 | values["completed"] 423 | 424 | elsif values.has_key?("completed") 425 | __temp_120 = 426 | 427 | values["completed"] 428 | 429 | end 430 | 431 | __temp_122 = nil 432 | 433 | 434 | if values.has_key?("created_at") 435 | __temp_122 = 436 | 437 | Jennifer::Model::TimeZoneConverter.from_hash(values, "created_at", self.class.columns_tuple[:created_at]) 438 | 439 | elsif values.has_key?("created_at") 440 | __temp_122 = 441 | 442 | Jennifer::Model::TimeZoneConverter.from_hash(values, "created_at", self.class.columns_tuple[:created_at]) 443 | 444 | end 445 | 446 | __temp_124 = nil 447 | 448 | 449 | if values.has_key?("updated_at") 450 | __temp_124 = 451 | 452 | Jennifer::Model::TimeZoneConverter.from_hash(values, "updated_at", self.class.columns_tuple[:updated_at]) 453 | 454 | elsif values.has_key?("updated_at") 455 | __temp_124 = 456 | 457 | Jennifer::Model::TimeZoneConverter.from_hash(values, "updated_at", self.class.columns_tuple[:updated_at]) 458 | 459 | end 460 | 461 | 462 | 463 | begin 464 | __temp_126 = 465 | 466 | (__temp_116.is_a?(String) ? self.class.coerce_id(__temp_116) : __temp_116) 467 | 468 | .as(Int32?) 469 | rescue e : Exception 470 | raise ::Jennifer::DataTypeCasting.match?(e) ? ::Jennifer::DataTypeCasting.new("id", Task, e) : e 471 | end 472 | 473 | begin 474 | __temp_127 = 475 | 476 | __temp_118 477 | 478 | .as(String) 479 | rescue e : Exception 480 | raise ::Jennifer::DataTypeCasting.match?(e) ? ::Jennifer::DataTypeCasting.new("title", Task, e) : e 481 | end 482 | 483 | begin 484 | __temp_128 = 485 | 486 | (__temp_120.is_a?(String) ? self.class.coerce_completed(__temp_120) : __temp_120) 487 | 488 | .as(Bool) 489 | rescue e : Exception 490 | raise ::Jennifer::DataTypeCasting.match?(e) ? ::Jennifer::DataTypeCasting.new("completed", Task, e) : e 491 | end 492 | 493 | begin 494 | __temp_129 = 495 | 496 | (__temp_122.is_a?(String) ? self.class.coerce_created_at(__temp_122) : __temp_122) 497 | 498 | .as(::Union(Time, ::Nil)) 499 | rescue e : Exception 500 | raise ::Jennifer::DataTypeCasting.match?(e) ? ::Jennifer::DataTypeCasting.new("created_at", Task, e) : e 501 | end 502 | 503 | begin 504 | __temp_130 = 505 | 506 | (__temp_124.is_a?(String) ? self.class.coerce_updated_at(__temp_124) : __temp_124) 507 | 508 | .as(::Union(Time, ::Nil)) 509 | rescue e : Exception 510 | raise ::Jennifer::DataTypeCasting.match?(e) ? ::Jennifer::DataTypeCasting.new("updated_at", Task, e) : e 511 | end 512 | 513 | 514 | 515 | { 516 | 517 | __temp_126, 518 | 519 | __temp_127, 520 | 521 | __temp_128, 522 | 523 | __temp_129, 524 | 525 | __temp_130, 526 | 527 | } 528 | 529 | end 530 | 531 | private def __refresh_changes 532 | 533 | @id_changed = false 534 | 535 | @title_changed = false 536 | 537 | @completed_changed = false 538 | 539 | @created_at_changed = false 540 | 541 | @updated_at_changed = false 542 | 543 | end 544 | 545 | private def save_record_under_transaction(skip_validation) : Bool 546 | is_new_record = new_record? 547 | return false unless save_without_transaction(skip_validation) 548 | 549 | adapter = self.class.write_adapter 550 | if is_new_record 551 | adapter.subscribe_on_commit(->__after_create_commit_callback) if HAS_CREATE_COMMIT_CALLBACK 552 | adapter.subscribe_on_rollback(->__after_create_rollback_callback) if HAS_CREATE_ROLLBACK_CALLBACK 553 | else 554 | adapter.subscribe_on_commit(->__after_update_commit_callback) if HAS_CREATE_COMMIT_CALLBACK 555 | adapter.subscribe_on_rollback(->__after_update_rollback_callback) if HAS_CREATE_ROLLBACK_CALLBACK 556 | end 557 | adapter.subscribe_on_commit(->__after_save_commit_callback) if HAS_SAVE_COMMIT_CALLBACK 558 | adapter.subscribe_on_rollback(->__after_save_rollback_callback) if HAS_SAVE_ROLLBACK_CALLBACK 559 | true 560 | end 561 | 562 | macro inherited 563 | # :nodoc: 564 | MODEL = true 565 | end 566 |
Warning: expanding macro
There was a problem expanding macro 'common_mapping'Called macro defined in lib/jennifer/src/jennifer/model/common_mapping.cr:5:5
5 | macro common_mapping(strict)
Which expanded to:
1 | 2 | 3 | __field_declaration({id: {type: Int32, primary: true, parsed_type: "Int32?", null: false, column: "id", auto: true}, title: {type: String, parsed_type: "String", null: false, column: "title"}, completed: {type: Bool, default: false, parsed_type: "Bool", null: false, column: "completed"}, created_at: {type: ::Union(Time, ::Nil), converter: Jennifer::Model::TimeZoneConverter, parsed_type: "::Union(Time, ::Nil)", null: true, column: "created_at"}, updated_at: {type: ::Union(Time, ::Nil), converter: Jennifer::Model::TimeZoneConverter, parsed_type: "::Union(Time, ::Nil)", null: true, column: "updated_at"}}, true) 4 | 5 | # :nodoc: 6 | def self.field_count : Int32 7 | 5 8 | end 9 | 10 | # :nodoc: 11 | FIELD_NAMES = ["id", "title", "completed", "created_at", "updated_at"] 12 | 13 | # :nodoc: 14 | def self.field_names : Array(String) 15 | ["id", "title", "completed", "created_at", "updated_at"] 16 | end 17 | 18 | def self.column_names : Array(String) 19 | ["id", "title", "completed", "created_at", "updated_at"] 20 | end 21 | 22 | # :nodoc: 23 | def self.columns_tuple 24 | COLUMNS_METADATA 25 | end 26 | 27 | # Creates object from `DB::ResultSet` 28 | def initialize(__temp_131 : DB::ResultSet) 29 | @new_record = false 30 | @id, @title, @completed, @created_at, @updated_at = _extract_attributes(__temp_131) 31 | end 32 | 33 | # :nodoc: -> 34 | def self.new(pull : DB::ResultSet) 35 | 36 | {% if true %} 37 | {% klasses = @type.all_subclasses.select do |s| 38 | (s.constant("STI")) == true 39 | end %} 40 | {% if !klasses.empty? %} 41 | hash = adapter.result_to_hash(pull) 42 | case hash["type"] 43 | when "", nil, "{{ @type }}" 44 | new(hash, false) 45 | {% for klass in klasses %} 46 | when "{{ klass }}" 47 | {{ klass }}.new(hash, false) 48 | {% end %} 49 | else 50 | raise ::Jennifer::UnknownSTIType.new(self, hash["type"]) 51 | end 52 | {% else %} 53 | instance = allocate 54 | instance.initialize(pull) 55 | instance.__after_initialize_callback 56 | instance 57 | {% end %} 58 | {% end %} 59 | 60 | end 61 | 62 | # Accepts symbol hash or named tuple, stringify it and calls constructor with string-based keys hash. 63 | def initialize(values : Hash(Symbol, AttrType) | NamedTuple) 64 | initialize(Ifrit.stringify_hash(values, AttrType)) 65 | end 66 | 67 | # :nodoc: 68 | def self.new(values : Hash(Symbol, AttrType) | NamedTuple) 69 | instance = allocate 70 | instance.initialize(values) 71 | instance.__after_initialize_callback 72 | instance 73 | end 74 | 75 | def initialize(values : Hash(String, AttrType)) 76 | @id, @title, @completed, @created_at, @updated_at = _extract_attributes(values) 77 | end 78 | 79 | # :nodoc: 80 | def self.new(values : Hash(String, AttrType)) 81 | instance = allocate 82 | instance.initialize(values) 83 | instance.__after_initialize_callback 84 | instance 85 | end 86 | 87 | # :nodoc: 88 | def initialize(values : Hash | NamedTuple, @new_record) 89 | initialize(values) 90 | end 91 | 92 | # :nodoc: 93 | def self.new(values : Hash | NamedTuple, new_record : Bool) 94 | instance = allocate 95 | instance.initialize(values, new_record) 96 | instance.__after_initialize_callback 97 | instance 98 | end 99 | 100 | # :nodoc: 101 | def to_h 102 | { 103 | 104 | :id => id, 105 | 106 | :title => title, 107 | 108 | :completed => completed, 109 | 110 | :created_at => created_at, 111 | 112 | :updated_at => updated_at, 113 | 114 | } of Symbol => AttrType 115 | end 116 | 117 | # :nodoc: 118 | def to_str_h 119 | { 120 | 121 | "id" => id, 122 | 123 | "title" => title, 124 | 125 | "completed" => completed, 126 | 127 | "created_at" => created_at, 128 | 129 | "updated_at" => updated_at, 130 | 131 | } of String => AttrType 132 | end 133 | 134 | # :nodoc: 135 | def attribute(name : String | Symbol, raise_exception : Bool = true) 136 | case name.to_s 137 | 138 | when "id" 139 | self.id 140 | 141 | when "title" 142 | self.title 143 | 144 | when "completed" 145 | self.completed 146 | 147 | when "created_at" 148 | self.created_at 149 | 150 | when "updated_at" 151 | self.updated_at 152 | 153 | else 154 | raise ::Jennifer::UnknownAttribute.new(name, self.class) if raise_exception 155 | end 156 | end 157 | 158 | # :nodoc: 159 | def attribute_before_typecast(name : String | Symbol) : ::Jennifer::DBAny 160 | case name.to_s 161 | 162 | when "id" 163 | 164 | self.id 165 | 166 | 167 | when "title" 168 | 169 | self.title 170 | 171 | 172 | when "completed" 173 | 174 | self.completed 175 | 176 | 177 | when "created_at" 178 | 179 | Jennifer::Model::TimeZoneConverter.to_db(self.created_at, self.class.columns_tuple[:created_at]) 180 | 181 | 182 | when "updated_at" 183 | 184 | Jennifer::Model::TimeZoneConverter.to_db(self.updated_at, self.class.columns_tuple[:updated_at]) 185 | 186 | 187 | else 188 | raise ::Jennifer::UnknownAttribute.new(name, self.class) 189 | end 190 | end 191 | 192 | private def init_attributes(values : Hash) 193 | @id, @title, @completed, @created_at, @updated_at = _extract_attributes(values) 194 | end 195 | 196 | private def init_attributes(values : DB::ResultSet) 197 | @id, @title, @completed, @created_at, @updated_at = _extract_attributes(values) 198 | end 199 |
Warning: positional parameter 'pull' corresponds to parameter 'values' of the overridden method Jennifer::Model::Base::AbstractClassMethods#new(values : Hash | NamedTuple), which has a different name and may affect named argument passing
A total of 2 warnings were found.
It doesn't seem to break anything as far as I can see but it's annoying to have these logs appearing everytime I run my specs or my server. Is this a bug or have I done something incorrectly ? 🤔
Hi, sorry for such a late response. What version do you use? Latest release version doesn't have this issue any more (0.13.0
)
Can confirm I don't have the error in 0.13.0 anymore 👍
Not sure was I didn't install this version to begin with 🤔
Thank you