I am using a Rails 2.3.x and Ruby 1.8.7 environment with FactoryGirl 1.3.3 (edit: version of FG has no influence as far as I can see)
In my console, when I do:
Factory(:user_activity)
I get:
#<UserActivity id: 25, user_id: 1, resource_id: nil, ... >
However when I do in my testcase:
#ua = Factory(:user_activity)
I get:
#<UserActivity id: 980190963, user_id: 298486374, resource_id: nil, ... >
Where are these large IDs coming from? How can I setup my testcases to use the expected IDs as seen in the console?
I suppose that the IDs are calculated in the same or an equivalent way as when using ActiveRecord fixtures (AR fixtures hashes the fixture label).
I don't know why using Factory in console will give you more normal IDs however.
Do you really need to know the ID in order to test? Or can you use your #ua variable to get the ID if you need it?
Related
I updated my Rails application to a newer version of Rails, and now one of my models is unusable, as if it was loaded empty, as if Rails was not aware of its structure and how to populate it.
This model is Task and is based on Single Table Inheritance:
class Activity < ActiveRecord::Base
(...)
end
class Task < Activity
(...)
end
class Event < Activity
(...)
end
class Phase < Activity
(...)
end
Here is what is expected when the model is loaded properly and everything works well (same model because of STI):
Activity.inspect => Activity(id: integer, type: string, project_id: integer, author_id: integer, subject: text, description: text, (...), created_at: datetime, updated_at: datetime)
Task.inspect => Task(id: integer, type: string, project_id: integer, author_id: integer, subject: text, description: text, (...), created_at: datetime, updated_at: datetime)
Event.inspect => Event(same model as above ...)
(...)
However, since the update, Rails is unable to use the Task model at all, neither for reading a record from the database or creating a new one. Other related models Event and Phase works as expected.
When I debug it in production mode by inspecting the Task class and Task.first from the Task controller # show I get:
Task.inspect => Task()
Task.first.inspect => #<Task >
Task.first.nil? => false
This model appears as if it was void. Others models are loaded perfectly.
The application does not fail with an error when Rails tries to load the record, but it fails later when the controller tries to access any field, because the model is empty.
Some important observations :
It only fails in production mode, but works well in development mode, or it fails only when config.cache_classes = true but works well otherwise.
It works well in the Rails console.
task.rb model file gets loaded even in the failing context. Model files structure is flat, all models are in app/models/
It used to work well before updating from Ruby 1.9.3 and Rails 3.1 to Ruby 2.3.8 and Rails 3.2.22.
This is probably a duplicate of https://stackoverflow.com/a/58867450/1388302
Something else is defining Task - maybe to extend it. Don't do that. Use prepend. Otherwise the autoloader finds that unintentional definition and won't load the one you intend.
Or Task is now also defined by something you're including. It might be interesting to ask about Task.superclass.
This probably came up because Rails 6 changed the autoloader.
Something looks buggy with respect to Rails 3.2.22 schema loading and STI.
The best workaround I found so far is to force schema reloading for this model using :
Task.connection.schema_cache.clear!
Task.reset_column_information
But then Rails looses track of STI and will miss adding the "type" field to the newly created records. So to force this fields, in every controller required, I added :
#task = (...).becomes(Task)
This feels hacky, but I could not find any better way. Maybe this tip will help someone else. In my case it was not an option to upgrade Rails further or to refactor all the code to get rid of STI.
I'm new at coding and I'm trying to implement RSpec testing to a command I made for my slack bot using Ruby.
The command retrieves the data from the database using .where(Time.zone.now.begining_of_day..Time.zone.now.end_of_day) => showed in the code down bellow.
map through each of them and format it for the user output
Code:
Class StartCommand
def call
Answer.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)
.map { |answer| "#{answer.slack_identifier}:\n#{answer.body}" }
.join("\n\n")
end
end
RSpec testing:
RSpec.describe RecordCommand do
describe '#call' do
it 'retrieves data and format it' do
StartCommand.new.call
expect(Answer.where).to eq()
end
end
As you can see I'm kinda lost how to implement the code in the RSpec testing, any ideas, hints or solutions would be awesome! Help!
Im using Ruby and Ruby on Rails 4
You can use the database-cleaner gem to wipe the DB between test runs. It lets you can create records in your test case as needed. It's also a good idea to use the timecop whenever you are testing anything time-related, since it freezes your test case at any time and removes the unpredictability of Time.now. Assuming you have installed those -
it 'retrieves data and format it' do
# Freeze time at a point
base_time = Time.zone.now.beginning_of_day + 5.minutes
Timecop.freeze(base_time) do
# setup, create db records
# 2 in the current day, 1 in the previous day
Answer.create(slack_identifier: "s1", body: "b1", created_at: base_time)
Answer.create(slack_identifier: "s2", body: "b2", created_at: base_time + 1.minute)
Answer.create(slack_identifier: "s3", body: "b3", created_at: base_time - 1.day)
# call the method and verify the results
expect(StartCommand.new.call).to eq("s1:\nb1\n\ns2:\nb2")
end
end
You may also want to add an order to your where query. I don't think you can guarantee that ActiveRecord returns records in the same order each time unless you specify it (see Rails 3: What is the default order of "MyModel.all"?), and specifying it would make the test more dependable
I know that one can use Pry to see what a model in composed of but is there a way to see the various attributes of a model in the Rails console without Pry? What is the command?
I know I can go looking at the migration but I'd rather stay in the command line where possible.
Thanks
From script/console or irb you can just issue the name of the class and it will return the attributes.
For instance, with a Post model:
>> Post
=> Post(id: integer, title: string, body: text, created_at: datetime)
I am using NetBeans to create my first Ruby on Rails application. Is there a way by which I can view all of the properties of a model? Should I just be looking in the database?
I just use db/schema.rb - seems to work fine for me.
You can use the annotate gem for this - it will add comments to the top of each model indicating its properties.
You could call Model.attributes in Rails' console. This gives a hash with all attributes.
Be careful when using this inside your real code as it always recreates the hash and is therefore pretty expensive.
Just type your model name on the rails console then press Enter.
rails c # start your rails console
User
=> User(id: integer, email: string, password_digest: string...)
In case anyone is viewing this and is using a newer version of Rails, you can just call Model in the console. (I'm on Rails 3.2.1 and Ruby 1.9.2p290.)
In fact, calling Model.attributes in this case does not work.
A nice little tool that I use is from MySQL. It is called MySQL Administrator.
It lets me validate that the db (development/test/production), the tables for the db, and finally the columns(attributes).
Model.attributes #=> {'name' => 'foo', 'desc' => 'bar'}
P.S. www.railsbrain.com - use this.
I seem to recall that there was a plugin or Rake snippet that would put comments in various Model classes after running a migration? It's a chore to have to look at db/migrate/X when I want to see which fields a given model has.
If not, I'll write one, of course. :)
There is a school of thought that suggests you you shouldn't put attribute comments in the model as it breaks the principal of DRY. I won't argue the point. However, one real nice way of identifying attributes of the model is to simply type the Model name when you are in ./script/console
> User
=> User(id: integer, loginname: string, password: string, fullname: string, created_at: datetime, updated_at: datetime)
I always have ./script/console session open when developing Rails.
You may be thinking of the Annotate Models plugin at:
http://repo.pragprog.com/svn/Public/plugins/annotate_models/
I believe that does exactly what you describe, although I haven't personally used it in a while, so can't vouch for its behaviour on more recent Rails versions.
Regards,
NeilS.
I maintain the annotate gem (which started life as that venerable plugin by Dave Thomas) and the latest version allows you to run
rails g annotate_models:install
which adds a rake file to your project. Afterwards, annotate will be executed whenever you run rake db:migrate (but only in development mode).
...currently this feature seems to be broken :-(