Skip to content
Open
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
62 changes: 50 additions & 12 deletions lib/her/model/parse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ def to_params
self.class.to_params(attributes, changes)
end

# Convert into a hash of request parameters, based on `include_root_in_embedded_json`.
def to_embedded_params
self.class.to_params(attributes, changes, true)
end

module ClassMethods
# Parse data before assigning it to a resource, based on `parse_root_in_json`.
#
Expand All @@ -31,7 +36,7 @@ def parse(data)
end

# @private
def to_params(attributes, changes = {})
def to_params(attributes, changes = {}, embedded = false)
filtered_attributes = attributes.each_with_object({}) do |(key, value), memo|
case value
when Her::Model
Expand All @@ -48,11 +53,14 @@ def to_params(attributes, changes = {})
filtered_attributes.slice! *changes.keys.map(&:to_sym)
end

if include_root_in_json?
include_element = embedded ? include_root_in_embedded_json? : include_root_in_json?
element = embedded ? included_embedded_root_element : included_root_element

if include_element
if json_api_format?
{ included_root_element => [filtered_attributes] }
{ element => [filtered_attributes] }
else
{ included_root_element => filtered_attributes }
{ element => filtered_attributes }
end
else
filtered_attributes
Expand All @@ -61,17 +69,25 @@ def to_params(attributes, changes = {})

# @private
def embeded_params(attributes)
associations.values.flatten.each_with_object({}) do |definition, hash|
value = case association = attributes[definition[:name]]
when Her::Collection, Array
association.map { |a| a.to_params }.reject(&:empty?)
when Her::Model
association.to_params
end
hash[definition[:data_key]] = value if value.present?
associations.keys.each_with_object({}) do |key, hash|
associations[key].flatten.each do |definition|
next if attributes[definition[:data_key]].present? && key.to_sym == :belongs_to
embeded_association(attributes, definition, hash)
end
end
end

# @private
def embeded_association(attributes, definition, hash)
value = case association = attributes[definition[:name]]
when Her::Collection, Array
association.map { |a| a.to_embedded_params }.reject(&:empty?)
when Her::Model
association.to_embedded_params
end
hash[definition[:data_key]] = value if value.present?
end

# Return or change the value of `include_root_in_json`
#
# @example
Expand All @@ -84,6 +100,17 @@ def include_root_in_json(value, options = {})
@_her_include_root_in_json_format = options[:format]
end

# Return or change the value of `include_root_in_embedded_json`
#
# @example
# class User
# include Her::Model
# include_root_in_embedded_json true
# end
def include_root_in_embedded_json(value)
@_her_include_root_in_embedded_json = value
end

# Return or change the value of `parse_root_in_json`
#
# @example
Expand Down Expand Up @@ -151,6 +178,11 @@ def included_root_element
include_root_in_json? == true ? root_element : include_root_in_json?
end

# @private
def included_embedded_root_element
include_root_in_embedded_json? == true ? root_element : include_root_in_embedded_json?
end

# Extract an array from the request data
#
# @example
Expand Down Expand Up @@ -212,6 +244,12 @@ def include_root_in_json?
superclass.respond_to?(:include_root_in_json?) && superclass.include_root_in_json?
end

# @private
def include_root_in_embedded_json?
return @_her_include_root_in_embedded_json unless @_her_include_root_in_embedded_json.nil?
superclass.respond_to?(:include_root_in_embedded_json?) && superclass.include_root_in_embedded_json?
end

# @private
def parse_root_in_json?
return @_her_parse_root_in_json unless @_her_parse_root_in_json.nil?
Expand Down
4 changes: 2 additions & 2 deletions spec/model/associations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
end

it "includes belongs_to relationship in params by default" do
expect(user_params[:organization]).to be_kind_of(Hash)
expect(user_params[:organization]).to be_a(Foo::Organization)
expect(user_params[:organization]).not_to be_empty
end
end
Expand Down Expand Up @@ -687,7 +687,7 @@
end

it "includes belongs_to relationship in params by default" do
expect(user_params[:organization]).to be_kind_of(Hash)
expect(user_params[:organization]).to be_a(Foo::Organization)
expect(user_params[:organization]).not_to be_empty
end
end
Expand Down
95 changes: 95 additions & 0 deletions spec/model/parse_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,101 @@ class User < Foo::Model; end
end
end

context "when include_root_in_embedded_json is set" do
before do
Her::API.setup url: "https://api.example.com" do |builder|
builder.use Her::Middleware::FirstLevelParseJSON
builder.use Faraday::Request::UrlEncoded
end

Her::API.default_api.connection.adapter :test do |stub|
stub.post("/users") { |env| [200, {}, { user: { id: 1, fullname: params(env)[:user][:fullname] } }.to_json] }
stub.post("/users/admins") { |env| [200, {}, { user: { id: 1, fullname: params(env)[:user][:fullname] } }.to_json] }
end
end

context "to true" do
before do
spawn_model "Foo::User" do
include_root_in_embedded_json true
parse_root_in_json true
custom_post :admins
end
end

it "inherits attributes from parent class" do
spawn_model "Foo::ChildUser", super_class: Foo::User do
end

expect(Foo::ChildUser).to be_include_root_in_embedded_json
end

it "allows `include_root_in_embedded_json` to be set to `false` on a child model" do
spawn_model "Foo::ChildUser", super_class: Foo::User do
include_root_in_embedded_json false
end

expect(Foo::ChildUser).to_not be_include_root_in_embedded_json
end

it "wraps params in the element name in `to_embedded_params`" do
@new_user = Foo::User.new(fullname: "Tobias Fünke")
expect(@new_user.to_embedded_params).to eq(user: { fullname: "Tobias Fünke" })
end
end

context "to false" do
before do
spawn_model "Foo::User" do
include_root_in_embedded_json false
end
end

it "inherits attributes from parent class" do
spawn_model "Foo::ChildUser", super_class: Foo::User do
end

expect(Foo::ChildUser).to_not be_include_root_in_embedded_json
end

it "allows `include_root_in_embedded_json` to be set to `true` on a child model" do
spawn_model "Foo::ChildUser", super_class: Foo::User do
include_root_in_embedded_json true
end

expect(Foo::ChildUser).to be_include_root_in_embedded_json
end
end

context "to a symbol" do
before do
spawn_model "Foo::User" do
include_root_in_embedded_json :person
parse_root_in_json :person
end
end

it "wraps params in the specified value" do
@new_user = Foo::User.new(fullname: "Tobias Fünke")
expect(@new_user.to_embedded_params).to eq(person: { fullname: "Tobias Fünke" })
end
end

context "in the parent class" do
before do
spawn_model("Foo::Model") { include_root_in_embedded_json true }

class User < Foo::Model; end
@spawned_models << :User
end

it "wraps params with the class name" do
@new_user = User.new(fullname: "Tobias Fünke")
expect(@new_user.to_embedded_params).to eq(user: { fullname: "Tobias Fünke" })
end
end
end

context "when `request_new_object_on_build` is set" do
context "to true" do
before do
Expand Down