diff --git a/CHANGELOG.md b/CHANGELOG.md index 12604664d..90de99b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # master/HEAD +## Features +- Improved Model build/create methods, allowing to pass arguments instead of NamedTuple + + +## Bug fixes + +## Breaking changes +- Renaming `insert` method on `InsertQuery` to `values`, making API more elegant. + +# v0.3 + ## Features - Add support to pg Enum - Add support for UUID primary key, with uuid autogeneration diff --git a/spec/model/model_spec.cr b/spec/model/model_spec.cr index 4ae7ffe01..5d6d8794b 100644 --- a/spec/model/model_spec.cr +++ b/spec/model/model_spec.cr @@ -127,8 +127,7 @@ module ModelSpec it "can load link string <-> varchar" do temporary do reinit - u = User.new({id: 1, first_name: "John", middle_name: "William"}) - u.save! + User.create!(id: 1, first_name: "John", middle_name: "William") User.query.each do |u| u.middle_name.should eq "William" diff --git a/spec/sql/insert_spec.cr b/spec/sql/insert_spec.cr index 342eb0d5a..5a5f543ad 100644 --- a/spec/sql/insert_spec.cr +++ b/spec/sql/insert_spec.cr @@ -12,7 +12,7 @@ module InsertSpec describe "Clear::SQL" do describe "InsertQuery" do it "can build an insert" do - insert_request.insert({a: "c", b: 12}).to_sql.should eq( + insert_request.values({a: "c", b: 12}).to_sql.should eq( "INSERT INTO users (a, b) VALUES ('c', 12)" ) end @@ -33,7 +33,7 @@ module InsertSpec end it "can insert unsafe values" do - insert_request.insert({created_at: Clear::Expression.unsafe("NOW()")}) + insert_request.values({created_at: Clear::Expression.unsafe("NOW()")}) .to_sql .should eq "INSERT INTO users (created_at) VALUES (NOW())" end diff --git a/src/clear/model/modules/class_methods.cr b/src/clear/model/modules/class_methods.cr index 4b470a853..6b5a38138 100644 --- a/src/clear/model/modules/class_methods.cr +++ b/src/clear/model/modules/class_methods.cr @@ -31,44 +31,44 @@ module Clear::Model::ClassMethods find(x).not_nil! end - # Build methods are used as factory and can - # be redefined in case of polymorphism - def self.build : self - self.new + def self.build(**x : **T) forall T + \\{% if T.size > 0 %} + self.new(x) + \\{% else %} + self.new + \\{% end %} end - def self.build(x : NamedTuple) : self - self.new(x) - end - - def self.create : self - mdl = build - mdl.save - mdl + # Multi-args or no-arg to named tuple + def self.create(**args) : self + mdl = build(**args) + mdl.save + mdl end - def self.create! : self - mdl = build - mdl.save! - mdl + # Multi-args to named tuple + def self.create!(**args) : self + mdl = build(**args) + mdl.save! + mdl end def self.create(x : Array(NamedTuple)) : Array(self) - x.map{ |elm| create(elm) } + x.map{ |elm| create(**elm) } end def self.create!(x : Array(NamedTuple)) : Array(self) - x.map{ |elm| create!(elm) } + x.map{ |elm| create!(**elm) } end def self.create(x : NamedTuple) : self - mdl = build(x) + mdl = build(**x) mdl.save mdl end def self.create!(x : NamedTuple) : self - mdl = build(x) + mdl = build(**x) mdl.save! mdl end diff --git a/src/clear/sql/insert_query.cr b/src/clear/sql/insert_query.cr index df97771b0..a78555679 100644 --- a/src/clear/sql/insert_query.cr +++ b/src/clear/sql/insert_query.cr @@ -23,12 +23,19 @@ class Clear::SQL::InsertQuery alias Inserable = ::Clear::SQL::Any | BigInt | BigFloat | Time getter keys : Array(Symbolic) = [] of Symbolic getter values : SelectBuilder | Array(Array(Inserable)) = [] of Array(Inserable) - getter table : Selectable + getter! table : Selectable getter returning : String? def initialize(@table : Selectable) end + def initialize(@table : Selectable, values) + self.values(values) + end + + def into(@table : Selectable) + end + def fetch(connection_name : String = "default", &block : Hash(String, ::Clear::SQL::Any) -> Void) Clear::SQL.log_query to_sql do h = {} of String => ::Clear::SQL::Any @@ -77,7 +84,7 @@ class Clear::SQL::InsertQuery # # insert({field: "value"}).into(:table) # - def insert(row : NamedTuple) + def values(row : NamedTuple) @keys = row.keys.to_a.map(&.as(Symbolic)) v = @values = [] of Array(Inserable) @@ -86,7 +93,7 @@ class Clear::SQL::InsertQuery change! end - def insert(row : Hash(Symbolic, Inserable)) + def values(row : Hash(Symbolic, Inserable)) @keys = row.keys.to_a.map(&.as(Symbolic)) v = @values = [] of Array(Inserable) @@ -95,6 +102,18 @@ class Clear::SQL::InsertQuery change! end + def values(rows : Array(NamedTuple)) + rows.each do |nt| + values(nt) + end + end + + def values(rows : Array(Hash(Symbolic, Inserable))) + rows.each do |nt| + values(nt) + end + end + # Used with values def columns(*args) @keys = args diff --git a/src/clear/sql/sql.cr b/src/clear/sql/sql.cr index 9b2d98e45..3d121733a 100644 --- a/src/clear/sql/sql.cr +++ b/src/clear/sql/sql.cr @@ -177,9 +177,18 @@ module Clear Clear::SQL::DeleteQuery.new(connection).from(table) end + def insert_into(table) + Clear::SQL::InsertQuery.new(table) + end + # Start an INSERT INTO table query def insert_into(table, *args) - Clear::SQL::InsertQuery.new(table).insert(*args) + Clear::SQL::InsertQuery.new(table).values(*args) + end + + # Create a new INSERT query + def insert + Clear::SQL::InsertQuery.new end # Alias of `insert_into`, for hurry developers