Model Association (Rails 5 API)











up vote
3
down vote

favorite












I have a Character model that has a CharClass and ClassPerks child.



Currently I am duplicating my logic a lot by manually assigning data.



My Character index and create:



def index

@campaign = Campaign.find_by_id(params[:campaign_id])
@characters = @campaign.characters
render json: {
characters: @characters
}
end

def create
@campaign = Campaign.find_by_id(params[:campaign_id])
@charClass = CharClass.find_by_id(params[:character_char_class_id])
@character = @campaign.characters.new(character_params)
@character.char_class_id = params[:character_char_class_id]

if @character.save!
render status: 201, json: {

message: "Successfull added this character to the campaign!",
character_name: @character.character_name + ' the ' + @charClass.class_name,
character_class: @charClass.class_name,
character_level: @character.character_level,
character_experience: @character.character_experience,
character_gold: @character.character_gold,
character_perks: get_names(@character.character_perks),
character_image: @character.character_image

}
else
render status: 404, json: {
message: "Something went wrong: Check line 24 of the Character Controller"
}
end
end


I am manually assigning character_class and character_image despite both of these ALWAYS being the same based on their character_class.



Inside of the character.rb I am doing this to assign them post-create:



    after_create :add_perks, :save_class

def add_perks
self.class_perks.each do |perk|
self.character_perks.create(class_perk_id: perk.id)
end
end


def save_class()
case self.char_class_id
when 1 # Mindthief
self.character_image = "https://gloomhavenil.files.wordpress.com/2017/12/11849117_616974988445216_217288420_n.jpg?w=480"
self.character_class = "Mindthief"
self.save
when 2 # Tinkerer
self.character_image = "http://www.cephalofair.com/wp-content/uploads/2015/04/Quatryl-Tinkerer.jpg"
self.character_class = "Tinkerer"
self.save
# when 'Sawbones'
# else
end
end
end


It is working, but I am unsure how to do this better/appropriately. I removed useless fields but you'll see below I have the relations set up appropriately.



  create_table "char_classes", force: :cascade do |t|
t.string "class_name"
t.string "class_image"
t.string "class_perks"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "characters", force: :cascade do |t|
t.string "character_class"
t.string "character_image"
t.integer "char_class_id"
t.index ["campaign_id"], name: "index_characters_on_campaign_id"
t.index ["char_class_id"], name: "index_characters_on_char_class_id"
end


I can do Character.first.char_class.class_name and I will get the appropriate result; so I am back to assuming this method I'm following is very incorrect.










share|improve this question
















bumped to the homepage by Community 15 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.



















    up vote
    3
    down vote

    favorite












    I have a Character model that has a CharClass and ClassPerks child.



    Currently I am duplicating my logic a lot by manually assigning data.



    My Character index and create:



    def index

    @campaign = Campaign.find_by_id(params[:campaign_id])
    @characters = @campaign.characters
    render json: {
    characters: @characters
    }
    end

    def create
    @campaign = Campaign.find_by_id(params[:campaign_id])
    @charClass = CharClass.find_by_id(params[:character_char_class_id])
    @character = @campaign.characters.new(character_params)
    @character.char_class_id = params[:character_char_class_id]

    if @character.save!
    render status: 201, json: {

    message: "Successfull added this character to the campaign!",
    character_name: @character.character_name + ' the ' + @charClass.class_name,
    character_class: @charClass.class_name,
    character_level: @character.character_level,
    character_experience: @character.character_experience,
    character_gold: @character.character_gold,
    character_perks: get_names(@character.character_perks),
    character_image: @character.character_image

    }
    else
    render status: 404, json: {
    message: "Something went wrong: Check line 24 of the Character Controller"
    }
    end
    end


    I am manually assigning character_class and character_image despite both of these ALWAYS being the same based on their character_class.



    Inside of the character.rb I am doing this to assign them post-create:



        after_create :add_perks, :save_class

    def add_perks
    self.class_perks.each do |perk|
    self.character_perks.create(class_perk_id: perk.id)
    end
    end


    def save_class()
    case self.char_class_id
    when 1 # Mindthief
    self.character_image = "https://gloomhavenil.files.wordpress.com/2017/12/11849117_616974988445216_217288420_n.jpg?w=480"
    self.character_class = "Mindthief"
    self.save
    when 2 # Tinkerer
    self.character_image = "http://www.cephalofair.com/wp-content/uploads/2015/04/Quatryl-Tinkerer.jpg"
    self.character_class = "Tinkerer"
    self.save
    # when 'Sawbones'
    # else
    end
    end
    end


    It is working, but I am unsure how to do this better/appropriately. I removed useless fields but you'll see below I have the relations set up appropriately.



      create_table "char_classes", force: :cascade do |t|
    t.string "class_name"
    t.string "class_image"
    t.string "class_perks"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    end

    create_table "characters", force: :cascade do |t|
    t.string "character_class"
    t.string "character_image"
    t.integer "char_class_id"
    t.index ["campaign_id"], name: "index_characters_on_campaign_id"
    t.index ["char_class_id"], name: "index_characters_on_char_class_id"
    end


    I can do Character.first.char_class.class_name and I will get the appropriate result; so I am back to assuming this method I'm following is very incorrect.










    share|improve this question
















    bumped to the homepage by Community 15 hours ago


    This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

















      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I have a Character model that has a CharClass and ClassPerks child.



      Currently I am duplicating my logic a lot by manually assigning data.



      My Character index and create:



      def index

      @campaign = Campaign.find_by_id(params[:campaign_id])
      @characters = @campaign.characters
      render json: {
      characters: @characters
      }
      end

      def create
      @campaign = Campaign.find_by_id(params[:campaign_id])
      @charClass = CharClass.find_by_id(params[:character_char_class_id])
      @character = @campaign.characters.new(character_params)
      @character.char_class_id = params[:character_char_class_id]

      if @character.save!
      render status: 201, json: {

      message: "Successfull added this character to the campaign!",
      character_name: @character.character_name + ' the ' + @charClass.class_name,
      character_class: @charClass.class_name,
      character_level: @character.character_level,
      character_experience: @character.character_experience,
      character_gold: @character.character_gold,
      character_perks: get_names(@character.character_perks),
      character_image: @character.character_image

      }
      else
      render status: 404, json: {
      message: "Something went wrong: Check line 24 of the Character Controller"
      }
      end
      end


      I am manually assigning character_class and character_image despite both of these ALWAYS being the same based on their character_class.



      Inside of the character.rb I am doing this to assign them post-create:



          after_create :add_perks, :save_class

      def add_perks
      self.class_perks.each do |perk|
      self.character_perks.create(class_perk_id: perk.id)
      end
      end


      def save_class()
      case self.char_class_id
      when 1 # Mindthief
      self.character_image = "https://gloomhavenil.files.wordpress.com/2017/12/11849117_616974988445216_217288420_n.jpg?w=480"
      self.character_class = "Mindthief"
      self.save
      when 2 # Tinkerer
      self.character_image = "http://www.cephalofair.com/wp-content/uploads/2015/04/Quatryl-Tinkerer.jpg"
      self.character_class = "Tinkerer"
      self.save
      # when 'Sawbones'
      # else
      end
      end
      end


      It is working, but I am unsure how to do this better/appropriately. I removed useless fields but you'll see below I have the relations set up appropriately.



        create_table "char_classes", force: :cascade do |t|
      t.string "class_name"
      t.string "class_image"
      t.string "class_perks"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      end

      create_table "characters", force: :cascade do |t|
      t.string "character_class"
      t.string "character_image"
      t.integer "char_class_id"
      t.index ["campaign_id"], name: "index_characters_on_campaign_id"
      t.index ["char_class_id"], name: "index_characters_on_char_class_id"
      end


      I can do Character.first.char_class.class_name and I will get the appropriate result; so I am back to assuming this method I'm following is very incorrect.










      share|improve this question















      I have a Character model that has a CharClass and ClassPerks child.



      Currently I am duplicating my logic a lot by manually assigning data.



      My Character index and create:



      def index

      @campaign = Campaign.find_by_id(params[:campaign_id])
      @characters = @campaign.characters
      render json: {
      characters: @characters
      }
      end

      def create
      @campaign = Campaign.find_by_id(params[:campaign_id])
      @charClass = CharClass.find_by_id(params[:character_char_class_id])
      @character = @campaign.characters.new(character_params)
      @character.char_class_id = params[:character_char_class_id]

      if @character.save!
      render status: 201, json: {

      message: "Successfull added this character to the campaign!",
      character_name: @character.character_name + ' the ' + @charClass.class_name,
      character_class: @charClass.class_name,
      character_level: @character.character_level,
      character_experience: @character.character_experience,
      character_gold: @character.character_gold,
      character_perks: get_names(@character.character_perks),
      character_image: @character.character_image

      }
      else
      render status: 404, json: {
      message: "Something went wrong: Check line 24 of the Character Controller"
      }
      end
      end


      I am manually assigning character_class and character_image despite both of these ALWAYS being the same based on their character_class.



      Inside of the character.rb I am doing this to assign them post-create:



          after_create :add_perks, :save_class

      def add_perks
      self.class_perks.each do |perk|
      self.character_perks.create(class_perk_id: perk.id)
      end
      end


      def save_class()
      case self.char_class_id
      when 1 # Mindthief
      self.character_image = "https://gloomhavenil.files.wordpress.com/2017/12/11849117_616974988445216_217288420_n.jpg?w=480"
      self.character_class = "Mindthief"
      self.save
      when 2 # Tinkerer
      self.character_image = "http://www.cephalofair.com/wp-content/uploads/2015/04/Quatryl-Tinkerer.jpg"
      self.character_class = "Tinkerer"
      self.save
      # when 'Sawbones'
      # else
      end
      end
      end


      It is working, but I am unsure how to do this better/appropriately. I removed useless fields but you'll see below I have the relations set up appropriately.



        create_table "char_classes", force: :cascade do |t|
      t.string "class_name"
      t.string "class_image"
      t.string "class_perks"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      end

      create_table "characters", force: :cascade do |t|
      t.string "character_class"
      t.string "character_image"
      t.integer "char_class_id"
      t.index ["campaign_id"], name: "index_characters_on_campaign_id"
      t.index ["char_class_id"], name: "index_characters_on_char_class_id"
      end


      I can do Character.first.char_class.class_name and I will get the appropriate result; so I am back to assuming this method I'm following is very incorrect.







      ruby ruby-on-rails






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 12 at 0:19









      Jamal

      30.2k11115226




      30.2k11115226










      asked Apr 12 at 0:08









      DNorthrup

      1855




      1855





      bumped to the homepage by Community 15 hours ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







      bumped to the homepage by Community 15 hours ago


      This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          You need to use ActiveModelSerializers (AMS) to serialize your json responses based upon the instances of your class.



          class CampaignsController < ApplicationController
          def index
          render json: { characters: campaign.characters }
          end

          def create
          @character = campaign.characters.new(character_params.merge(char_class_id: char_class.id))

          if @character.save!
          render json: @character, serializer: CharacterSerializer, status: 201 # This should automatically be formatted by AMS
          else
          not_found('Something went wrong: Check line 24 of the Character Controller')
          end
          end

          private

          def campaign
          @campaign ||= Campaign.find_by_id(params[:campaign_id])
          end

          def char_class
          @charClass ||= CharClass.find_by_id(params[:character_char_class_id])
          end
          end


          This is how you AMS class for Character class should look like



          class CharacterSerializer < ActiveModel::Serializer
          attributes :message, :character_name, :character_class, :character_level, :character_experience, :character_gold, :character_perks, :character_image

          def message
          'Successfull added this character to the campaign!'
          end

          def character_name
          return object.character_name + ' the ' + character_class # check the associations
          end

          def character_class
          object.charClass.class_name
          end

          def character_perks
          # Unsure what this get names methods does so im leaving it for you to refactor
          get_names(object.character_perks),
          end

          end


          Also add this to your ApplicationController



          class ApplicationController < ActionController::Base

          # Add this to your application controller

          def not_found(message = nil)
          render json: { message }, status: 404
          end

          end


          I'll update the refactored model class based upon your info soon. Hope this helps for now.






          share|improve this answer























            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191831%2fmodel-association-rails-5-api%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            You need to use ActiveModelSerializers (AMS) to serialize your json responses based upon the instances of your class.



            class CampaignsController < ApplicationController
            def index
            render json: { characters: campaign.characters }
            end

            def create
            @character = campaign.characters.new(character_params.merge(char_class_id: char_class.id))

            if @character.save!
            render json: @character, serializer: CharacterSerializer, status: 201 # This should automatically be formatted by AMS
            else
            not_found('Something went wrong: Check line 24 of the Character Controller')
            end
            end

            private

            def campaign
            @campaign ||= Campaign.find_by_id(params[:campaign_id])
            end

            def char_class
            @charClass ||= CharClass.find_by_id(params[:character_char_class_id])
            end
            end


            This is how you AMS class for Character class should look like



            class CharacterSerializer < ActiveModel::Serializer
            attributes :message, :character_name, :character_class, :character_level, :character_experience, :character_gold, :character_perks, :character_image

            def message
            'Successfull added this character to the campaign!'
            end

            def character_name
            return object.character_name + ' the ' + character_class # check the associations
            end

            def character_class
            object.charClass.class_name
            end

            def character_perks
            # Unsure what this get names methods does so im leaving it for you to refactor
            get_names(object.character_perks),
            end

            end


            Also add this to your ApplicationController



            class ApplicationController < ActionController::Base

            # Add this to your application controller

            def not_found(message = nil)
            render json: { message }, status: 404
            end

            end


            I'll update the refactored model class based upon your info soon. Hope this helps for now.






            share|improve this answer



























              up vote
              0
              down vote













              You need to use ActiveModelSerializers (AMS) to serialize your json responses based upon the instances of your class.



              class CampaignsController < ApplicationController
              def index
              render json: { characters: campaign.characters }
              end

              def create
              @character = campaign.characters.new(character_params.merge(char_class_id: char_class.id))

              if @character.save!
              render json: @character, serializer: CharacterSerializer, status: 201 # This should automatically be formatted by AMS
              else
              not_found('Something went wrong: Check line 24 of the Character Controller')
              end
              end

              private

              def campaign
              @campaign ||= Campaign.find_by_id(params[:campaign_id])
              end

              def char_class
              @charClass ||= CharClass.find_by_id(params[:character_char_class_id])
              end
              end


              This is how you AMS class for Character class should look like



              class CharacterSerializer < ActiveModel::Serializer
              attributes :message, :character_name, :character_class, :character_level, :character_experience, :character_gold, :character_perks, :character_image

              def message
              'Successfull added this character to the campaign!'
              end

              def character_name
              return object.character_name + ' the ' + character_class # check the associations
              end

              def character_class
              object.charClass.class_name
              end

              def character_perks
              # Unsure what this get names methods does so im leaving it for you to refactor
              get_names(object.character_perks),
              end

              end


              Also add this to your ApplicationController



              class ApplicationController < ActionController::Base

              # Add this to your application controller

              def not_found(message = nil)
              render json: { message }, status: 404
              end

              end


              I'll update the refactored model class based upon your info soon. Hope this helps for now.






              share|improve this answer

























                up vote
                0
                down vote










                up vote
                0
                down vote









                You need to use ActiveModelSerializers (AMS) to serialize your json responses based upon the instances of your class.



                class CampaignsController < ApplicationController
                def index
                render json: { characters: campaign.characters }
                end

                def create
                @character = campaign.characters.new(character_params.merge(char_class_id: char_class.id))

                if @character.save!
                render json: @character, serializer: CharacterSerializer, status: 201 # This should automatically be formatted by AMS
                else
                not_found('Something went wrong: Check line 24 of the Character Controller')
                end
                end

                private

                def campaign
                @campaign ||= Campaign.find_by_id(params[:campaign_id])
                end

                def char_class
                @charClass ||= CharClass.find_by_id(params[:character_char_class_id])
                end
                end


                This is how you AMS class for Character class should look like



                class CharacterSerializer < ActiveModel::Serializer
                attributes :message, :character_name, :character_class, :character_level, :character_experience, :character_gold, :character_perks, :character_image

                def message
                'Successfull added this character to the campaign!'
                end

                def character_name
                return object.character_name + ' the ' + character_class # check the associations
                end

                def character_class
                object.charClass.class_name
                end

                def character_perks
                # Unsure what this get names methods does so im leaving it for you to refactor
                get_names(object.character_perks),
                end

                end


                Also add this to your ApplicationController



                class ApplicationController < ActionController::Base

                # Add this to your application controller

                def not_found(message = nil)
                render json: { message }, status: 404
                end

                end


                I'll update the refactored model class based upon your info soon. Hope this helps for now.






                share|improve this answer














                You need to use ActiveModelSerializers (AMS) to serialize your json responses based upon the instances of your class.



                class CampaignsController < ApplicationController
                def index
                render json: { characters: campaign.characters }
                end

                def create
                @character = campaign.characters.new(character_params.merge(char_class_id: char_class.id))

                if @character.save!
                render json: @character, serializer: CharacterSerializer, status: 201 # This should automatically be formatted by AMS
                else
                not_found('Something went wrong: Check line 24 of the Character Controller')
                end
                end

                private

                def campaign
                @campaign ||= Campaign.find_by_id(params[:campaign_id])
                end

                def char_class
                @charClass ||= CharClass.find_by_id(params[:character_char_class_id])
                end
                end


                This is how you AMS class for Character class should look like



                class CharacterSerializer < ActiveModel::Serializer
                attributes :message, :character_name, :character_class, :character_level, :character_experience, :character_gold, :character_perks, :character_image

                def message
                'Successfull added this character to the campaign!'
                end

                def character_name
                return object.character_name + ' the ' + character_class # check the associations
                end

                def character_class
                object.charClass.class_name
                end

                def character_perks
                # Unsure what this get names methods does so im leaving it for you to refactor
                get_names(object.character_perks),
                end

                end


                Also add this to your ApplicationController



                class ApplicationController < ActionController::Base

                # Add this to your application controller

                def not_found(message = nil)
                render json: { message }, status: 404
                end

                end


                I'll update the refactored model class based upon your info soon. Hope this helps for now.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Apr 12 at 4:12

























                answered Apr 12 at 4:00









                Aniket Rao

                1012




                1012






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191831%2fmodel-association-rails-5-api%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Morgemoulin

                    Scott Moir

                    Souastre