4
\$\begingroup\$

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.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 12, 2018 at 0:08
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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.

answered Apr 12, 2018 at 4:00
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.