Code Monkey home page Code Monkey logo

tutor-server's Introduction

Tests Migrations Coverage

OpenStax Tutor Backend Server

The following installations instructions assume you use APT (Linux) or Homebrew (OS X). Please install the package management software appropriate for your OS, if necessary. We also recommend getting the latest package definitions/Homebrew version using:

  • Linux: sudo apt-get update
  • OS X: brew update

You will need a specific version of ruby installed to run tutor-server. We recommend using rbenv to manage your ruby versions and ruby-build to compile new versions of ruby.

Follow the installation instructions for rbenv and ruby-build

After installing all the prerequisites, git clone the tutor-server repository and cd into it:

git clone https://github.com/openstax/tutor-server.git
cd tutor-server

Then install the proper version of ruby using rbenv:

rbenv install 2.7.2

Make sure that which ruby and which gem point to your .rbenv folder, NOT /usr/bin or /usr/local/bin. If either of them are pointing to the wrong folder and you did modify your path according to rbenv's installation instructions, you might need to restart your shell.

Then install bundler:

gem install bundler

Once again, make sure that which bundle points to your .rbenv folder. Restart your shell if that's not the case.

Then install the required gems:

bundle install

Permanently setting environment variables

You can permanently set environment variables by creating a .env file in the tutor-server folder containing your desired default environment variables and their values. For an example, see the .env.frontend_example file.

Configuring PostgreSQL for Development and Testing

OpenStax Tutor uses the PostgreSQL database. You'll need to install and configure that:

  • Linux: sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev
  • OS X: brew install postgresql

Once installed, create a superuser for Tutor. By default Tutor will expect a user ox_tutor who has a password ox_tutor_secret_password:

createuser --superuser --pwprompt ox_tutor

Then type ox_tutor_secret_password for the password in the prompt.

These PostgreSQL username and password for Tutor can be overridden by setting environment variables. See the config/database.yml file for details.

You can tell Tutor to setup its databases:

bin/rake db:setup

If you ever need to clear the database contents, use:

bin/rake db:reset

If you end up with conflicts in your schema.rb file, run the following command to re-create it from scratch:

bin/rake db:drop db:create db:migrate db:seed

If Tutor is still unable to connect to the database, you may have to update your pg_hba.conf. Open that file with your favorite text editor:

  • Linux: sudo your-text-editor /etc/postgresql/<version>/main/pg_hba.conf
  • OS X: sudo your-text-editor /usr/local/var/postgres/pg_hba.conf

Change peer to md5 or create a new md5 entry for localhost (127.0.0.1). Then restart the PostgreSQL daemons with:

  • Linux: sudo service postgresql restart
  • OS X: sudo brew services restart postgresql

Once Tutor is up and running the database superuser role can be safely removed from the user. However, it is convenient to leave ox_tutor as a superuser so you can easily drop and re-create its databases if necessary. To remove the superuser role:

psql -Uox_tutor ox_tutor_dev
ALTER USER ox_tutor NOSUPERUSER;

To quit the PostgreSQL shell, type \q.

Configuring Redis server for Development and Testing

You will need a Redis server running in order to use tutor-server:

  • Linux: sudo apt-get install redis-server
  • OS X: brew install redis

If the server is remote (not running on localhost), it can be configured in config/secrets.yml.

Starting tutor-server

Once PostgreSQL and Redis are configured, you can start the tutor-server process:

bin/rails s

By default, it will bind to port 3001 (so you can access it from https://localhost:3001). You can specify a custom port with the -p command line option. A development console is also available by running:

bin/rails c

Error Pages/Responses

By default, the development and test environments see different error responses than the production environment. Dev and test environments will see HTML responses with backtraces and helpful debugging information, but the production environment will see nicely-formatted HTML error pages or simple JSON responses.

Our frontend developers often use the development environment during testing but will likely want to see production-like error responses. To achieve this, set a USE_DEV_ERROR_RESPONSES environment variable to false. This can be achieved by setting USE_DEV_ERROR_RESPONSES=false in your .env file. A .env.frontend_example file is available in the repository for FE devs to copy over to .env. The recommended behavior is to do this and then only switch to a true setting if you need to debug the BE (see backtraces, etc).

Background Jobs

Tutor in production runs background jobs using delayed_job. In the development environment, however, background jobs are run "inline", i.e. in the foreground.

To actually run these jobs in the background in the development environment, set the environment variable USE_REAL_BACKGROUND_JOBS=true in your .env file and then start the delayed_job daemon:

bin/rake jobs:work

Bullet

Bullet is a gem for finding N+1 queries and the like. To enable it in development, set an ENABLE_BULLET environment variable to true. Then you can tail log/bullet.log. Beware that this will slow down the server considerably.

Testing with capybara

Capybara-webkit depends on Qt. To install Qt:

  • Linux: sudo apt-get install qt5-default libqt5webkit5-dev
  • OS X: brew install qt

Running specs in parallel

OpenStax Tutor can optionally run its specs using the parallel_tests gem. This can result in the test suite completing 4-5 times faster depending on how many CPU cores the testing environment has available.

To create the parallel test databases:

bin/rake parallel:create parallel:prepare

To upgrade the databases after migrations, run:

bin/rake parallel:prepare

If you had to solve migration or schema conflicts, use the following commands to erase all data and start from scratch:

bin/rake db:drop db:create db:migrate db:seed
bin/rake parallel:drop parallel:create parallel:prepare

To run the test suite in parallel, use:

bin/rake parallel:spec

Be aware that canceling the parallel specs will NOT print the failed specs so far. It can also leave some processes running that interfere with future test runs. Kill them (and any other ruby processes) with sudo killall -9 ruby.

Running Demos

A demo rake task exists to populate the database with certain courses and scenarios. The demos assume that appropriate data has been loaded into CNX and Exercises.

Before running the task you should reset the database:

bin/rake db:reset demo

The courses that are set up in the demo are determined by the YAML files in the directories under the config/demo directory.

Each directory under demo represents an entire course, as a set of YAML files.

It is in these files that you can configure different periods, student membership in periods, CNX book UUID and version, assignments and progress on those assignments, etc.

By default, all YAML files in the directories under the review directory are run, in the order import', users, course, assign, work`.

You can run a single step as a separate rake task, as so:

bin/rake demo:import

or bin/rake demo:course

If you want to only run a diffent whole suite, you can specify its name in the rake call, e.g. to load the "test" suit you would say:

bin/rake db:reset demo[test]

As an admin you can search for the various users set up by the demo scripts (or you can check out the demo YAML files in config/demo/review/users).

A teacher is setup with the reviewteacher username.

The full list of teachers and students can be found here.

Additional courses can be created by dumping existing courses (from a production server) and copying the created YAML file tree into config/demo

Profiling

See this napkin note.

Features and Associated Code

LMS Integration

Tutor Responsibilities

  1. Provide configuration info that lets teachers (later admins) configure Tutor within an LMS.
  2. Handling the "launch" when an LMS directs one of its users to Tutor.
  3. Sending scores back to the LMS.

Feature Flags

LMS integration within Tutor can be turned off/on by course-level feature flags. Each course has a is_lms_enabling_allowed flag and an is_lms_enabled flag. Admins control the former, teachers control the latter. In order for a teacher to enable LMS integration, the is_lms_enabling_allowed flag must be true. Admins can search by this flag and bulk set this flag on any admin course search query results.

Major Code Files

  1. app/controllers/lms_controller.rb - Runs launches and provides config info when installing the Tutor app in an LMS.
  2. app/controllers/api/v1/lms_controller.rb - How the FE gets a course's LMS keys and triggers sending of scores to the LMS.
  3. app/subsystems/lms/launch.rb - wraps and interprets launch HTTP requests and provides convenience methods to interact with Tutor's LMS models.
  4. app/subsystems/lms/send_course_scores.rb - background job that sends scores to the LMS
  5. app/subsystems/lms/models/... - DB models that wrap LMS related data we need to persist

tutor-server's People

Contributors

brittany-johnson avatar bryanhouston avatar camliu89 avatar cnuber avatar dak avatar dantemss avatar darrenmason avatar dependabot[bot] avatar fredasaurus avatar gregfitch avatar jivey avatar joemsak avatar jpslav avatar karenc avatar karinamendez avatar kevinburleigh75 avatar m1yag1 avatar meeragovindaraju avatar nathanstitt avatar navilan avatar pandafulmanda avatar philschatz avatar pwolfert avatar reedstrm avatar royejohnson avatar steveburkett avatar tomwoodward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tutor-server's Issues

Implement substeps

We need at least FreeResponse, MultipleChoice and Feedback substeps or similar.
Remove their fields from the TaskedExercise.
Make the TaskedExerciseRepresenter delegate to a substep representer (this representer might need to look at previous steps too)

Remove orphaned migrations

These migrations are orphaned -- remove and fix any specs.

db/migrate/20140724184800_create_administrators.rb
db/migrate/20140923195826_create_courses.rb
db/migrate/20140923195940_create_sections.rb
db/migrate/20140923200039_create_educators.rb

Add subsystem API wrappers

Work like entities, but would provide readonly access to some of the object's attributes and potentially wouldn't need their own tables.

A prime candidate for this is Content::Models::Exercise, which is currently often used outside the Content subsystem.

Replace implementation of GetBookToc with VisitBook

Content::Api::VisitBook is a new routine for traversing a book structure and reporting back information. I wrote it to get exercise and tag information out of a book, but to test it at first I wrote a visitor to compute the table of contents like how we do in GetBookToc.

To simplify code, replace GetBookToc with this new VisitBook routine.

Explore overriding ActiveRecord's association attachment methods

As part of the SubSystems extraction, ActiveRecord fails to auto-detect the class_name of associated models when they're specified by a belongs_to/has_many/has_one.

To work around we've like to override the creation methods above and specify the class_name ourselves in one spot rather than listing them on every single association.

Our current implementation uses alias_method and ActiveRecord::Base.define_singleton_method to directly inject methods onto ActiveRecord. This could probably be extracted into a module that we can mix into the classes that need the functionality.

Prepend redis namespaces with "tutor_"?

Redis namespaces are global in our deployments right? (e.g. Exercises and Tutor share the same redis server and therefore their namespaces can collide). If this is the case, then I think the default (and deployment configured) namespaces need to be prepended with "tutor_" and the like?

e.g. these dev settings:
https://github.com/openstax/tutor-server/blob/master/config/secrets.yml.example#L20-L21

also in the other environments and I imagine each repository.

cc @cnuber @Dantemss

Avoid validations during lazy load of url and title in TaskedExercise

A TaskedExercise's url and title are lazily persisted in a way that conflicts with the fact that these models aren't to be updated after they are completed. This results in continual save failures over and over, evidenced by begin transaction rollback transaction pairs in the logs.

Instead of

def url
  u = super
  return u unless u.nil?
  u = wrapper.url
  self.url = u
  save if persisted?
  u
end

do something like

def url
  u = super # could also say u = read_attribute(:url)
  return u unless u.nil?
  u = wrapper.url
  self.update_attribute(:url, u) if persisted? # skips validations
  u
end

or you could eliminate the repeated code with

def url
  get_or_lazily_store(:url)
end

def title
  get_or_lazily_store(:title)
end

def get_or_lazily_store(attribute_name)
  value = read_attribute(attribute_name)
  return value if value.present?

  value = wrapper.send(attribute_name)
  self.update_attribute(attribute_name, value) if persisted?
  value
end

Background job assignment creation

Unicorns making assignments are being killed in tutor-demo because they are taking longer than 30 seconds. Move assignment creation to a background job.

Performance API test does not run on its own

When running rspec spec/controllers/api/v1/courses_controller_spec.rb, all the tests pass.

When running just the performance tests
rspec ./spec/controllers/api/v1/courses_controller_spec.rb:699

it 'should work on the happy path' do
or
rspec ./spec/controllers/api/v1/courses_controller_spec.rb:644
, the test fails:

  1) Api::V1::CoursesController with book #performance should work on the happy path
     Failure/Error: expect(resp).to eq([{

       expected: [{:period_id=>"1", :data_headings=>[{:title=>"Homework 2 task plan", :average=>87.5}, {:title=>"Reading task plan"}, {:title=>"Homework task plan", :average=>75.0}], :students=>[{:name=>"Student One", :role=>2, :data=>[{:type=>"homework", :id=>9, :status=>"completed", :exercise_count=>4, :correct_exercise_count=>3, :recovered_exercise_count=>0}, {:type=>"reading", :id=>1, :status=>"completed"}, {:type=>"homework", :id=>5, :status=>"completed", :exercise_count=>6, :correct_exercise_count=>6, :recovered_exercise_count=>0}]}, {:name=>"Student Two", :role=>3, :data=>[{:type=>"homework", :id=>10, :status=>"in_progress", :exercise_count=>3, :correct_exercise_count=>1, :recovered_exercise_count=>0}, {:type=>"reading", :id=>2, :status=>"in_progress"}, {:type=>"homework", :id=>6, :status=>"in_progress", :exercise_count=>5, :correct_exercise_count=>2, :recovered_exercise_count=>0}]}]}, {:period_id=>"2", :data_headings=>[{:title=>"Homework 2 task plan"}, {:title=>"Reading task plan"}, {:title=>"Homework task plan", :average=>100.0}], :students=>[{:name=>"Student Three", :role=>4, :data=>[{:type=>"homework", :id=>11, :status=>"not_started", :exercise_count=>3, :correct_exercise_count=>0, :recovered_exercise_count=>0}, {:type=>"reading", :id=>3, :status=>"not_started"}, {:type=>"homework", :id=>7, :status=>"completed", :exercise_count=>6, :correct_exercise_count=>6, :recovered_exercise_count=>0}]}, {:name=>"Student Four", :role=>5, :data=>[{:type=>"homework", :id=>12, :status=>"not_started", :exercise_count=>3, :correct_exercise_count=>0, :recovered_exercise_count=>0}, {:type=>"reading", :id=>4, :status=>"not_started"}, {:type=>"homework", :id=>8, :status=>"not_started", :exercise_count=>5, :correct_exercise_count=>0, :recovered_exercise_count=>0}]}]}]
            got: [{:period_id=>"1", :data_headings=>[{:title=>"Homework 2 task plan", :average=>87.5}, {:title=>"Reading task plan"}, {:title=>"Homework task plan", :average=>75.0}], :students=>[{:name=>"Student One", :role=>2, :data=>[{:type=>"homework", :id=>9, :status=>"completed", :exercise_count=>4, :correct_exercise_count=>3, :recovered_exercise_count=>0}, {:type=>"reading", :id=>1, :status=>"completed"}, {:type=>"homework", :id=>5, :status=>"completed", :exercise_count=>6, :correct_exercise_count=>6, :recovered_exercise_count=>0}]}, {:name=>"Student Two", :role=>3, :data=>[{:type=>"homework", :id=>10, :status=>"in_progress", :exercise_count=>4, :correct_exercise_count=>1, :recovered_exercise_count=>0}, {:type=>"reading", :id=>2, :status=>"in_progress"}, {:type=>"homework", :id=>6, :status=>"in_progress", :exercise_count=>6, :correct_exercise_count=>2, :recovered_exercise_count=>0}]}]}, {:period_id=>"2", :data_headings=>[{:title=>"Homework 2 task plan"}, {:title=>"Reading task plan"}, {:title=>"Homework task plan", :average=>100.0}], :students=>[{:name=>"Student Three", :role=>4, :data=>[{:type=>"homework", :id=>11, :status=>"not_started", :exercise_count=>4, :correct_exercise_count=>0, :recovered_exercise_count=>1}, {:type=>"reading", :id=>3, :status=>"not_started"}, {:type=>"homework", :id=>7, :status=>"completed", :exercise_count=>6, :correct_exercise_count=>6, :recovered_exercise_count=>0}]}, {:name=>"Student Four", :role=>5, :data=>[{:type=>"homework", :id=>12, :status=>"not_started", :exercise_count=>4, :correct_exercise_count=>0, :recovered_exercise_count=>0}, {:type=>"reading", :id=>4, :status=>"not_started"}, {:type=>"homework", :id=>8, :status=>"not_started", :exercise_count=>6, :correct_exercise_count=>0, :recovered_exercise_count=>1}]}]}]

       (compared using ==)

       Diff:

       @@ -26,14 +26,14 @@
              [{:type=>"homework",
                :id=>10,
                :status=>"in_progress",
       -        :exercise_count=>3,
       +        :exercise_count=>4,
                :correct_exercise_count=>1,
                :recovered_exercise_count=>0},
               {:type=>"reading", :id=>2, :status=>"in_progress"},
               {:type=>"homework",
                :id=>6,
                :status=>"in_progress",
       -        :exercise_count=>5,
       +        :exercise_count=>6,
                :correct_exercise_count=>2,
                :recovered_exercise_count=>0}]}]},
         {:period_id=>"2",

       @@ -48,9 +48,9 @@
              [{:type=>"homework",
                :id=>11,
                :status=>"not_started",
       -        :exercise_count=>3,
       +        :exercise_count=>4,
                :correct_exercise_count=>0,
       -        :recovered_exercise_count=>0},
       +        :recovered_exercise_count=>1},
               {:type=>"reading", :id=>3, :status=>"not_started"},
               {:type=>"homework",
                :id=>7,


       @@ -64,14 +64,14 @@
              [{:type=>"homework",
                :id=>12,
                :status=>"not_started",
       -        :exercise_count=>3,
       +        :exercise_count=>4,
                :correct_exercise_count=>0,
                :recovered_exercise_count=>0},
               {:type=>"reading", :id=>4, :status=>"not_started"},
               {:type=>"homework",
                :id=>8,
                :status=>"not_started",
       -        :exercise_count=>5,
       +        :exercise_count=>6,
                :correct_exercise_count=>0,
       -        :recovered_exercise_count=>0}]}]}]
       +        :recovered_exercise_count=>1}]}]}]

Optimize spec run time

A lot of our specs use imported content. Since importing a book page automatically imports the exercises in that page, and imported exercises automatically import a lot of tag objects, this process is making our specs slow. One potential way to solve this is to import the sample content once, before any of the specs run, then reuse that content in all specs, like a fixture.

Production readiness isues

  1. The demo script should pull the exercises server name from the config.
  2. Change debug -> info as logging configuration in produciton config.

Move GetCourseTaskPlans into Tasks subsystem

  1. Move GetCourseTaskPlans to Tasks::GetTaskPlans
  2. change it to take an owner field instead of a course
  3. Make it just output :plans -- some representer somewhere can deal with items and total_count if needed.
class Tasks::GetTaskPlans
  lev_routine express_output: :plans

  protected

  def exec(owner:)
    outputs[:plans] = Tasks::Models::TaskPlan.where(owner: owner).to_a
  end
end

I CAN HAZ CONSISTENT /api/user/courses and /api/courses/1???

/api/user/courses yields all the roles but not the periods and /api/courses/1 yields all the periods but not the roles.

Can either both contain both information or have one that contains both information?

FE always calls /api/user/courses because it needs to know whether to display the course listing but does not "technically" need the period info).

cc @pandafulmanda, @nathanstitt

Need to fix exercise URL's

Throughout the tutor-server app, exercise URL's are missing an /api/. Need to fix this in all places at once.

Wrap Lev::Status in Job model, add representer

This work depends on #392's updates to the JobController....

Right now, if the FE requests status on a job that is no longer in redis (say it expired or was otherwise removed), we'll get a nil error in:

https://github.com/openstax/tutor-server/blob/master/app/controllers/api/v1/jobs_controller.rb#L5-L6

Ideally we'd be able to report an "unknown" state if the UUID isn't present in redis. We'd also like to hide away the Lev::Status stuff.

Add a app/models/job.rb model that hides Lev::Status and is able to report information for unknown jobs, e.g.

class Job
  def self.find(uuid)
    Job.new(uuid)
  end

  def state
    @status.nil? ? "unknown" : @status['state']
  end

  def http_status_code
    # code that is in the controller now, might even just return 
    # :ok and :accepted instead of 200 and 202
  end

  # ... more methods to expose standard properties of Lev::Status

  # ... maybe using method_missing and respond_to? to pass on other routine-specified 
  # fields (some way to pass them on anyway)

  protected

  def initialize(uuid)
    # freak out if uuid nil
    @status = Lev::Status.find(uuid)
  end
end

Add a Api::V1::JobRepresenter to spit out JSON for the Job. Adding a representer will give us our standard way to document what information can be found in a job.

The representer will need a way to add properties for the routine-specified fields. Probably makes sense to add a data property in the representer that wraps all of the routine-specific fields:

property :data,
         ...
         getter: ->(*) { 
           # `self` is the `Job` instance
           self.job_specific_fields.each do
             # some iteration to slice out the job-specific fields
             # into this `data` json
           end
         }

The representer should always report the uuid and other standard fields (like the progress, etc).

Modify the JobController to just get the Job object and represent with the new representer, remembering to still report the correct status

Store chapter # and section # when importing CNX book

The front end will need to know chapter and section numbers, e.g. Chapter 4, Section 4.2, etc.

This information isn't included in the CNX data explicitly, we just need to keep count as we import the book (using 0-based indexing, which is a little odd for a book, but there's a reason for it).

Need to add a "number" string field (or some other name) to Book and Page. Each new level of nesting will add another ".". E.g. in College Physics that has only chapters and sections, the numbers will be "X" for chapters and "X.Y" for sections (each module / Page is a section). For Bio, there are units above chapters, so sections would be "X.Y.Z" (three levels down).

For now, don't worry about representing this in an API, just store the value. Talk to @Dantemss about where to look. @philschatz can later fill us in about how to deal with "X.0" chapter introduction "sections.

demo rake task features

This is mostly here so Dante/Kevin can check off (or remove)

TaskPlans:

  • >= 1 iReading with stats
  • >= 1 homework with stats
  • make some date ranges overlap
  • make 1 span to another month

Tasks

  • 1 In-progress iReading (or the same task twice) with:
    • 1 step with "Try another"
    • 1 step with "Remind me"
  • 1 Graded task with correct/incorrect answers
  • 1 Graded task with an unanswered step
  • >= 1 HW in the future
  • >= 1 iReading in the future

Nomethoderror: undefined method `return' for Timecop:Class when running `db:reset`

Stacktrace:

stderr: rake aborted!
NoMethodError: undefined method `return' for Timecop:Class
/home/osttutor/src/tutor-913f30c/config/initializers/timecop.rb:18:in `load_time'
/home/osttutor/src/tutor-913f30c/config/initializers/timecop.rb:24:in `<top (required)>'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/engine.rb:652:in `block in load_config_initializer'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/notifications.rb:166:in `instrument'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/engine.rb:651:in `load_config_initializer'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/engine.rb:616:in `block (2 levels) in <class:Engine>'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/engine.rb:615:in `each'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/engine.rb:615:in `block in <class:Engine>'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:30:in `instance_exec'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:30:in `run'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:55:in `block in run_initializers'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:44:in `each'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:44:in `tsort_each_child'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/initializable.rb:54:in `run_initializers'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/application.rb:352:in `initialize!'
/home/osttutor/src/tutor-913f30c/config/environment.rb:19:in `<top (required)>'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `block in require'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/application.rb:328:in `require_environment!'
/home/osttutor/src/tutor-913f30c/vendor/bundle/ruby/2.1.0/gems/railties-4.2.0/lib/rails/application.rb:443:in `block in run_tasks_blocks'
Tasks: TOP => db:reset => environment
(See full trace by running task with --trace)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.