Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add json options #120

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions spec/granite_orm/associations/has_many_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ require "../../spec_helper"

{% for adapter in GraniteExample::ADAPTERS %}
{%
teacher_constant = "Teacher#{adapter.camelcase.id}".id
klass_constant = "Klass#{adapter.camelcase.id}".id
student_constant = "Student#{adapter.camelcase.id}".id
teacher_constant = "Teacher#{adapter.camelcase.id}".id
klass_constant = "Klass#{adapter.camelcase.id}".id
student_constant = "Student#{adapter.camelcase.id}".id
enrollment_constant = "Enrollment#{adapter.camelcase.id}".id

adapter_suffix = "_#{adapter.id}".id
Expand Down
17 changes: 12 additions & 5 deletions spec/granite_orm_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ end

class Review < Granite::ORM::Base
adapter pg
field name : String
field user_id : Int32
field name : String, json: {filter: ->(name : String?) { name.try &.upcase }}
field user_id : Int32, json: {as: author_id}
field upvotes : Int64
field sentiment : Float32
field sentiment : Float32, json: {filter: ->(sentiment : Float32?) { sentiment.to_s }}
field interest : Float64
field published : Bool
field created_at : Time
field published : Bool, json: {hidden: true}
field created_at : Time, json: {hidden: true}
end

class WebSite < Granite::ORM::Base
Expand Down Expand Up @@ -108,6 +108,13 @@ describe Granite::ORM::Base do
s.custom_id = 3
s.to_json.should eq %({"custom_id":3,"name":"Hacker News"})
end

it "provides some options" do
r = Review.new(name: "Author", user_id: 7, upvotes: 1_i64, sentiment: 1.62, interest: 2.72, published: true, created_at: Time.now)
result = %({"id":null,"name":"AUTHOR","author_id":7,"upvotes":1,"sentiment":"1.62","interest":2.72})

r.to_json.should eq result
end
end

describe "validating fields" do
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "spec"

module GraniteExample
ADAPTERS = ["pg","mysql","sqlite"]
ADAPTERS = ["pg", "mysql", "sqlite"]
@@model_classes = [] of Granite::ORM::Base.class

extend self
Expand Down
18 changes: 9 additions & 9 deletions spec/spec_models.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ end
adapter_suffix = "_#{adapter.id}".id
adapter_literal = adapter.id

parent_table = "parent_#{ adapter_literal }s".id
student_table = "student_#{ adapter_literal }s".id
teacher_table = "teacher_#{ adapter_literal }s".id
klass_table = "klass_#{ adapter_literal }s".id
enrollment_table = "enrollment_#{ adapter_literal }s".id
school_table = "school_#{ adapter_literal }s".id
nation_county_table = "nation_county_#{ adapter_literal }s".id
parent_table = "parent_#{adapter_literal}s".id
student_table = "student_#{adapter_literal}s".id
teacher_table = "teacher_#{adapter_literal}s".id
klass_table = "klass_#{adapter_literal}s".id
enrollment_table = "enrollment_#{adapter_literal}s".id
school_table = "school_#{adapter_literal}s".id
nation_county_table = "nation_county_#{adapter_literal}s".id

if adapter == "pg"
primary_key_sql = "BIGSERIAL PRIMARY KEY".id
Expand All @@ -26,8 +26,8 @@ end
elsif adapter == "mysql"
primary_key_sql = "BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY".id
foreign_key_sql = "BIGINT".id
created_at_sql = "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,".id
updated_at_sql = "updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,".id
created_at_sql = "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,".id
updated_at_sql = "updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,".id
timestamp_fields = "timestamps".id
elsif adapter == "sqlite"
primary_key_sql = "INTEGER NOT NULL PRIMARY KEY".id
Expand Down
2 changes: 1 addition & 1 deletion src/granite_orm/associations.cr
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module Granite::ORM::Associations
{{children_class}}.all(query, id)
end
end

# define getter for related children
macro has_many(children_table, through)
def {{children_table.id}}
Expand Down
42 changes: 26 additions & 16 deletions src/granite_orm/fields.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ module Granite::ORM::Fields
end

# specify the fields you want to define and types
macro field(decl)
{% FIELDS[decl.var] = decl.type %}
macro field(decl, **options)
{% FIELDS[decl.var] = options || {} of Nil => Nil %}
{% FIELDS[decl.var][:type] = decl.type %}
end

# include created_at and updated_at that will automatically be updated
Expand All @@ -22,8 +23,8 @@ module Granite::ORM::Fields

macro __process_fields
# Create the properties
{% for name, type in FIELDS %}
property {{name.id}} : Union({{type.id}} | Nil)
{% for name, options in FIELDS %}
property {{name.id}} : Union({{options[:type].id}} | Nil)
{% end %}
{% if SETTINGS[:timestamps] %}
property created_at : Time?
Expand All @@ -32,7 +33,7 @@ module Granite::ORM::Fields

# keep a hash of the fields to be used for mapping
def self.fields(fields = [] of String)
{% for name, type in FIELDS %}
{% for name, options in FIELDS %}
fields << "{{name.id}}"
{% end %}
{% if SETTINGS[:timestamps] %}
Expand All @@ -45,8 +46,8 @@ module Granite::ORM::Fields
# keep a hash of the params that will be passed to the adapter.
def params
parsed_params = [] of DB::Any
{% for name, type in FIELDS %}
{% if type.id == Time.id %}
{% for name, options in FIELDS %}
{% if options[:type].id == Time.id %}
parsed_params << {{name.id}}.try(&.to_s("%F %X"))
{% else %}
parsed_params << {{name.id}}
Expand All @@ -64,7 +65,8 @@ module Granite::ORM::Fields

fields["{{PRIMARY[:name]}}"] = {{PRIMARY[:name]}}

{% for name, type in FIELDS %}
{% for name, options in FIELDS %}
{% type = options[:type] %}
{% if type.id == Time.id %}
fields["{{name}}"] = {{name.id}}.try(&.to_s("%F %X"))
{% elsif type.id == Slice.id %}
Expand All @@ -85,13 +87,20 @@ module Granite::ORM::Fields
json.object do
json.field "{{PRIMARY[:name]}}", {{PRIMARY[:name]}}

{% for name, type in FIELDS %}
%field, %value = "{{name.id}}", {{name.id}}
{% if type.id == Time.id %}
json.field %field, %value.try(&.to_s("%F %X"))
{% elsif type.id == Slice.id %}
json.field %field, %value.id.try(&.to_s(""))
{% else %}
{% for name, options in FIELDS %}
{% json_options = options[:json] || {} of Nil => Nil %}
{% type = options[:type] %}
{% unless json_options[:hidden] %}
%field = "{{(json_options[:as] || name).id}}"
%value = {% if (filter = json_options[:filter]) && filter.is_a? ProcLiteral %}
{{filter}}.call({{name.id}})
{% elsif type.id == Time.id %}
{{name.id}}.try(&.to_s("%F %X"))
{% elsif type.id == Slice.id %}
{{name.id}}.try(&.to_s(""))
{% else %}
{{name.id}}
{% end %}
json.field %field, %value
{% end %}
{% end %}
Expand All @@ -116,7 +125,8 @@ module Granite::ORM::Fields
# Casts params and sets fields
private def cast_to_field(name, value : Type)
case name.to_s
{% for _name, type in FIELDS %}
{% for _name, options in FIELDS %}
{% type = options[:type] %}
when "{{_name.id}}"
return @{{_name.id}} = nil if value.nil?
{% if type.id == Int32.id %}
Expand Down
4 changes: 2 additions & 2 deletions src/granite_orm/querying.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ module Granite::ORM::Querying

model.\{{primary_name}} = result.read(\{{primary_type}})

\{% for name, type in FIELDS %}
model.\{{name.id}} = result.read(Union(\{{type.id}} | Nil))
\{% for name, options in FIELDS %}
model.\{{name.id}} = result.read(Union(\{{options[:type].id}} | Nil))
\{% end %}

\{% if SETTINGS[:timestamps] %}
Expand Down