ruby require relative quesiton - ruby-on-rails

Hello I am trying to learn how to make a ruby on rails app. I am stuck on the require_relative syntax. Currently I have a game_runner.rb file, that is not in the app directory, that is supposed to get a method (who_is_hider) from role.rb that is in models. Am I typing it correctly? When I run the current code I get an "uninitialized constant ApplicationRecord" error. This makes no sense since I have a application_record.rb file that has (self.abstract_class = true) inside. Thank you for your time.
game_runner.rb
require_relative './app/models/Role'
who_is_hider
role.rb
class Role < ApplicationRecord
belongs_to :round
belongs_to :player
enum label: {seeker: 1, hider: 2, decoy: 3}
validates :player_id, uniqueness: {scope: :round_id}
def who_is_hider
p "made it here"
end
end
application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

I am stuck on the require_relative syntax. […] Am I typing it correctly? When I run the current code I get an "uninitialized constant ApplicationRecord" error.
Yes, your syntax is correct. If your syntax were incorrect, your code wouldn't even run in the first place, and you would get a SyntaxError. The fact that your code does run and produce a NameError exception shows without a doubt that your syntax is correct.
As an easy way to check whether your syntax is correct, you can
visually inspect the syntax coloring in your editor,
visually inspect the syntax coloring in the Stack Overflow question, if you post one,
run ruby -c to check the syntax
The last one is the preferred option if you have it available, of course. But sometimes, you are writing code in an environment where you don't have a Ruby execution engine available, and in that case, you can at least use your editor or even the (admittedly not very good and easily confused) highlighting that Stack Overflow uses. While especially the latter one is not very good, it still does tend to highlight easy mistakes caused by typos, e.g. unterminated string literals.

Hmmm, you are using a single ruby file and expecting to load all rails environment? your Role model knows about ApplicationRecord because Rails loads a LOT of things on the background. If Rails is not in the middle then you have to explicitlly tell what thinks to load. You can require ApplicationRecord on the game_runner file or inside role.rb, but then you'll have to require ActiveRecord too.
I don't think it's a good idea to do what you are trying to do. If you wan't to run some script that depends on your environment, I'd recommend you to use a rake task, it will handle the loading of the environment. If you still want to make your game_runner.rb run as is, then you'll have to import everything the interpreter complains about until it works.

Related

Rails "superclass mismatch for class (TypeError)". A well documented error, but I need some tailored advice

Ok. I understand why I'm getting this error. According to another StackOverflow question, "That error shows up when you redeclare a class that’s already been declared". This question seems to point out the solutions, but not quite. I have some additional questions.
Here's what I have...
/models/item.rb
class Item < ActiveRecord::Base
..
end
class Theme < Item
end
class Setting < Item
end
This Item model has existed for quite some time. I recently added the sing inheritance for Theme and Setting.
As well as...
/models/setting.rb
class Setting < ActiveRecord::Base
..
end
/models/theme.rb
class Theme < ActiveRecord::Base
..
end
So it makes sense why I'm getting the error. I never got the error in my local workspace, only when I pushed everything to heroku, did my migrations, and then tried to run "heroku run rails c". As soon as I run that command, I get the error and immediately get booted out.
According to some answers, I should quit console and come back in. However, I can't get in to begin with. As soon as I launch "heroku run rails c", I get booted.
Additionally, if I completely wipe my DB, and remigrate everything, am I going to get the same error given the order of operations of these table creates, etc? I don't want to have to hack a solution to fix it everytime. If I run all my migrations, ideally everything would be working straight away.
What do I do to solve this issue?
You're trying to redefine the Theme and the Setting model. In your app/models/item.rb you define them as inherited from Item class and in the app/models/theme.rb and app/models/setting.rb you define them to inherit from ActiveRecord::Base directly.
You can see this error only in the heroku (probably production) environment because in dev env the eager loding option is turned off by default and therefore Rails does not load in all the classess when it boots.
Is your Item model using single table inheritance (STI)? Because that is the only case when you need to inherit the Theme and Settings model from your Item model.
If it is move your Theme and Setting class definitions to the app/models/theme.rb and app/models/setting.rb files accordingly and remove the definitions from there.
If not, then simply remove the Theme and Setting class definitions from the app/models/item.rb file and you'll be good to go.

How to successfully inherit ActiveRecord::Base?

How to successfully inherit ActiveRecord::Base?
Environment: Ruby 2.0.0, Rails 4.0.3, Windows 8.1, PostreSQL 9.3.3, Devise 3.2.4
I have an operational app and would like to add a comprehensive logging class to it. This will be a complex class that not only logs messages but also creates an SQL database that logs transactions by object. I need this class available throughout all of the classes in the application.
To do this, I wanted to inherit ActiveRecord::Base into the class and then have all other classes inherit it, though I don't plan to use STI. That seemed to be a lot simpler in concept than in practice, even though I thought such inheritance was a common best practice. Am I missing something?
One of the initial tables was this:
class Device < ActiveRecord::Base
...
end
I set it up like this:
class XLog < ActiveRecord::Base
self.abstract_class = true
def initialize
end
end
class Device < XLog
...
end
Prior to this change, the app was working fine. After this change, when I login I receive:
ArgumentError at /devices/sign_in
wrong number of arguments (1 for 0)
The error occurs in:
bin/rails, line 4
bin/rails is:
#!/usr/bin/env ruby.exe
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
Device is the Devise "User" class in this application and the error occurs when I try to login. If I change Device to inherit ActiveRecord::Base, it lets me login and run.
But, then I get another error whenever I call "new" on the other classes:
undefined method `[]' for nil:NilClass
I am definitely missing something when it comes to this inheritance. Advice appreciated.
The initialize method was throwing the error. It was triggering every time a subclass was initialized and was configured to accept 0 parameters. When I removed it, the whole thing started working. If I need it, I'll have to configure it to accept a variable number of parameters and pass them as expected, I guess.

Rails Test::Unit test of model validation surprisingly slow – I18n?

I have a simple test in my Rails app which is consistently taking much longer than other apparently similar tests.
It takes 1 to 2 seconds of real time to run test_invalid_without_name as below:
VALID_PARAMS = { name: 'Client record' }
def test_invalid_without_name
c = Client.new(VALID_PARAMS)
c.name = nil
refute c.valid?, 'should not be valid without a name'
end
The next test, test_valid_with_all_params takes less than 1/100th of a second:
def test_valid_with_all_params
c = Client.new(VALID_PARAMS)
assert c.valid?, 'should be valid with appropriate parameters'
end
The Client model is totally straightforward at this stage:
class Client < ActiveRecord::Base
belongs_to :entity, polymorphic: true
validates :name, presence: true
end
Can anyone either spot what’s wrong here, or give me an idea where I should look next to try to figure this out?
Update 1
I have used ruby-prof to profile the code, and it seems much of the time is being spent in the Psych gem. I believe this is used in ActiveRecord::..#serialize, which I am using in another model as follows:
class Opportunity < ActiveRecord::Base
belongs_to :client
serialize :details, Hash
end
However, removing the call to serialize here doesn’t make any difference to the Client tests (and I can’t see why it would, the two classes are associated, but no Opportunities are instantiated in the Client test).
Update 2
Turns out Psych is being called because I18n is using it. My assumption at this point is that the failed validation causes I18n to go to the locale files to pull out an error message. I will look into stubbing out I18n for testing...
It turns out a suitable approach to solving this was to use ruby-prof as follows.
Add to Gemfile (in the development group):
gem 'ruby-prof'
Wrap the test code in calls to the profiler:
def test_invalid_without_name
RubyProf.start
cr = Client.new(VALID_PARAMS)
cr.name = nil
refute cr.valid?, 'should not be valid without a name'
result = RubyProf.stop
printer = RubyProf::CallStackPrinter.new(result)
printer.print(File.open(File.join(Rails.root, 'profile_invalid_without_name.html'), 'w'))
end
This will create an interactive HTML document at the root of your Rails app, which shows the breakdown of where the time is spent.
In this case, it was 80%+ in I18n looking for translations. I added the following line to config/environments/test.rb to stub it out in testing:
I18n.backend = I18n::Backend::KeyValue.new({})
I will probably make the following additional improvements in future:
Be more specific with where I stub out I18n, so that full-stack acceptance tests can use the real thing.
Write a more convenient profiling approach. It looks like ruby-prof offers various other mechanisms for activating it, this was just the simplest for initial use.
It's not possible to answer the question without more information.
Does this happen when you run the each of tests individually?
Do you have anything in the setup/teardown or your test_helper.rb?
Does it happen if you pass a hash with name => nil instead of setting it?
Did you redefine the name setter?
Do you have any callbacks on your model?

stack level too deep (when changing model inheritance)

I'm trying to use the citier gem to convert some models that already exist in the following way. So far this works:
Created models:
Attachable < ActiveRecord::Base
Link < Attachable
I added acts_as_citier to both models, created and ran the migrations with no problem. Database views are created as well. Now if I try to do this to an existing model:
Before:
SpecialLink < ActiveRecord::Base
After:
SpecialLink < Link
and then I try to run any command like rails g migration or rails console, I get:
script/rails:6: stack level too deep (SystemStackError)
Unfortunately, this doesn't tell me a whole lot beyond a suspicion that I have an infinite loop somewhere. Does anyone know what might be causing this? Or have an idea of where I can look or get more information about the issue? It would not be a good solution for me to have to create the models again from scratch to work with citier...

ruby ::Module or just Module

I'm slowly making my way through the rails source, to get a better grip on ruby and rails in general. In the following rails class test_case.rb
the line is
class TestCase < ::Test::Unit::TestCase
and I was wondering if there is any difference with doing the following
class TestCase < Test::Unit::TestCase
It may seem trivial, but these things matter picking up a new language. The tests still run for ActiveSupport if I remove the leading :: so what does it do... :P
::Test ensures that you get a toplevel module named Test.
The latter case (Test::Unit::TestCase) doesn't ensure that Test is a toplevel module, it could be a class, for example. It means that most of the time, it'll work, but you could accidentally break it.
Imagine you have this code
module UserTesting
class Test # Details about a simple test
end
class TestCases < Test::Unit::TestCase
end
end
# => NameError: uninitialized constant UserTesting::Test::Unit
This would error out since your Test constant available to the class you are creating has no Unit constant in it. If you address it by :: this is like the leading slash in a path.
There is also a special case for using these - you can be evaluating your code in something else than the default root namespace, and there you actually need the double colon to address classes like ::Object (usually to monkeypatch them).

Resources