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)
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.
maybe I'm missing something, but I did research and could not find out why this is behaving like it does. I'm working with Rails 2.3.16 and ruby 1.9.3, backed by a huge ibm-db2.
Lets assume I have a class Foo (I tried to build a short example here)
class Foo < ActiveRecord::Base
end
The class has attributes: phone (integer) and mail (string).
When I use the Rails console to debug
bundle exec ./script/console , or
RAILS_ENV=production bundle exec ./script/console
I can load a Foo instance by doing:
f = Foo.find_by_phone(123)
=> #<Foo phone: false, mail: "test#example.org">
If I try to use the getter-method to get the phone-attribute:
f.phone
=> false
But the information must be there, because rails i) found the object and ii) you could do this yaml-output:
y f
---- !ruby/object:Foo
attributes:
phone: 123
mail: test#example.org
attributes_cache: {}
Thanks guys for helping me in advance, I'm sure I overlooked something!
The problem seems to be, that ActiveRecord interprets the DB2 short type as boolean. Is it possible to change that (stupid?) behavior?
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?
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 :-(