diff --git a/lib/jsonapi/basic_resource.rb b/lib/jsonapi/basic_resource.rb index 65e8f57d..3b3d0095 100644 --- a/lib/jsonapi/basic_resource.rb +++ b/lib/jsonapi/basic_resource.rb @@ -246,10 +246,9 @@ def reflect_relationship?(relationship, options) def _create_to_many_links(relationship_type, relationship_key_values, options) relationship = self.class._relationships[relationship_type] - relation_name = relationship.relation_name(context: @context) if options[:reflected_source] - @model.public_send(relation_name) << options[:reflected_source]._model + _create_to_many_link(relationship, options[:reflected_source]) return :completed end @@ -274,15 +273,24 @@ def _create_to_many_links(relationship_type, relationship_key_values, options) end @reload_needed = true else - unless @model.public_send(relation_name).include?(related_resource._model) - @model.public_send(relation_name) << related_resource._model - end + _create_to_many_link(relationship, related_resource) end end :completed end + def _create_to_many_link(relationship, related_resource) + relation_name = relationship.relation_name(context: @context) + return if @model.public_send(relation_name).include?(related_resource._model) + + if relationship.options[:create_method] + public_send(relationship.options.fetch(:create_method), related_resource._model) + else + @model.public_send(relation_name) << related_resource._model + end + end + def _replace_to_many_links(relationship_type, relationship_key_values, options) relationship = self.class._relationship(relationship_type) diff --git a/test/controllers/controller_test.rb b/test/controllers/controller_test.rb index e2568f97..545eca2f 100644 --- a/test/controllers/controller_test.rb +++ b/test/controllers/controller_test.rb @@ -1637,6 +1637,40 @@ def test_create_relationship_to_many_join_table_record_exists assert_equal [502,503,505], post_object.tag_ids end + def test_create_relationship_to_many_with_create_method_option + PostResource.class_eval do + has_many :super_tags, acts_as_set: true, relation_name: :special_tags, class_name: 'Tag', + create_method: :add_super_tag + def add_super_tag(tag) + tag.update!(name: "#{tag.name}[super]") + @model.special_post_tags.create!(tag: tag) + end + end + + set_content_type_header! + + tag_502_name = Tag.find(502).name + tag_503_name = Tag.find(503).name + + put :create_relationship, params: {post_id: 3, relationship: 'super_tags', data: [{type: 'tags', id: 502}, {type: 'tags', id: 503}]} + + assert_response :no_content + post_object = Post.find(3) + assert_equal 2, post_object.special_tags.collect { |tag| tag.id }.length + assert matches_array? [502, 503], post_object.special_tags.collect { |tag| tag.id } + assert_equal "#{tag_502_name}[super]", Tag.find(502).name + assert_equal "#{tag_503_name}[super]", Tag.find(503).name + + tag_505_name = Tag.find(505).name + + post :create_relationship, params: {post_id: 3, relationship: 'super_tags', data: [{type: 'tags', id: 502}, {type: 'tags', id: 505}]} + + assert_response :no_content + post_object.reload + assert_equal [502,503,505], post_object.special_tag_ids + assert_equal "#{tag_505_name}[super]", Tag.find(505).name + end + def test_update_relationship_to_many_missing_tags set_content_type_header! put :update_relationship, params: {post_id: 3, relationship: 'tags'} diff --git a/test/test_helper.rb b/test/test_helper.rb index 42a86c9a..b20cca53 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -62,7 +62,9 @@ class TestApp < Rails::Application config.active_support.halt_callback_chains_on_return_false = false config.active_record.time_zone_aware_types = [:time, :datetime] config.active_record.belongs_to_required_by_default = false - unless Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR < 2 || Rails::VERSION::MAJOR == 6 && Rails::VERSION::MINOR >= 1 + unless Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR < 2 || + Rails::VERSION::MAJOR == 6 && Rails::VERSION::MINOR >= 1 || + Rails::VERSION::MAJOR > 6 config.active_record.sqlite3.represent_boolean_as_integer = true end end @@ -221,6 +223,7 @@ class CatResource < JSONAPI::Resource jsonapi_resources :posts do jsonapi_relationships jsonapi_links :special_tags + jsonapi_links :super_tags, only: [:create] end jsonapi_resources :sections jsonapi_resources :iso_currencies