Разработвам двигател, който да се използва в редица други приложения. Той предоставя някои основни Player
и Action
функционалности за приложения, използващи концепции за геймификация.
Двигателят има Player
модел с основни атрибути и методи, които съм тествал отделно (с RSpec) и всичко работи самостоятелно. Интегрирам двигателя с друго приложение и цялата функционалност по подразбиране е наред, но когато се опитам да разширя модела Player
на приложението с допълнителни атрибути, те го правят в db, но не са достъпни от клас Ruby. Подозрението ми е, че проблемът е свързан с факта, че класовете Player
имат едно и също име и че класът на приложението наследява от класа на двигателя, но не мога да разбера точния проблем и как да го поправя.
Обяснение /кодът следва:
Файлове на двигателя
Клас играч на двигателя:
module CoreEngine
class Player < ActiveRecord::Base
belongs_to :user, class_name: CoreEngine.user_class
has_many :player_actions
def add_action(some_action)
self.player_actions.create(action: some_action)
end
def add_actions(array_of_actions)
array_of_actions.each do |action|
self.add_action(action)
end
end
def total_score
self.player_actions.sum(:points_earned)
end
end
end
Схема на плейъра на двигателя:
create_table "core_engine_players", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.integer "user_id"
end
lib/core_engine/engine.rb
module CoreEngine
class Engine < ::Rails::Engine
isolate_namespace CoreEngine
config.generators do |g|
g.test_framework :rspec, :fixture => false
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
g.assets false
g.helper false
end
end
end
lib/core_engine.rb
require "core_engine/engine"
module CoreEngine
mattr_accessor :player_class
mattr_accessor :action_class
mattr_accessor :user_class
def self.root
File.expand_path(File.dirname(File.dirname(__FILE__)))
end
def self.models_dir
"#{root}/app/models/core_engine/"
end
def self.controllers_dir
"#{root}/app/controllers/core_engine/"
end
end
Файлове на приложението
config/initializers/core_engine.rb
CoreEngine.player_class = "Player"
Включих правилно скъпоценния камък core_engine (не е показан тук)
Клас Player на приложението (забележете, че се наследява от двигателя):
class Player < CoreEngine::Player
end
Схема на плейъра на приложението
create_table "players", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.integer "energy"
t.integer "credits"
end
Забележете по-горе, че присъстват energy
и credits
. Също така проверих, че те са в действителната таблица на Postgres чрез psql
:
Table "public.players"
Column | Type | Modifiers
------------+-----------------------------+------------------------------------------------------
id | integer | not null default nextval('players_id_seq'::regclass)
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
user_id | integer |
energy | integer |
credits | integer |
Indexes:
"players_pkey" PRIMARY KEY, btree (id)
Не получавам никакви грешки при мигрирането. Независимо от това, когато стартирам rails конзола и извикам Player
, получавам:
2.1.1p76 :001 > Player
=> Player(id: integer, created_at: datetime, updated_at: datetime, name: string, user_id: integer)
Няма energy
да се намери никъде. Сигурен съм, че е свързано с наследяването от модела Player
на двигателя, но не виждам какъв е всъщност проблемът. Мога да дефинирам методи в модела Player
на приложението, които то може да извиква, както и методи в модела Player
на двигателя, които и двете могат да извикват, но не и атрибути като този.
Предполагам, че бих могъл потенциално да използвам изрични методи за достъп до тези определено съществуващи колони на базата данни, но бих предпочел, ако мога просто да използвам Rails/ActiveRecord както обикновено.
Това е първият ми опит с двигатели (първата публикация също!) и всичко беше много положително до сега. Всяка помощ ще бъде високо оценена!