I have a model which uses STI:
class Contributor::Name < Contributor::NameBase
...
end
From this model:
class Contributor::NameBase < ActiveRecord::Base
...
end
Whenever Contributor::Name gets instantiated, I receive this error:
Mysql2::Error: Table 'shelflives_development.contributor_basis_name_bases' doesn't exist: SHOW FULL FIELDS FROM `contributor_basis_name_bases`
It seems that instead of looking up the table contributor_name_bases, ActiveRecord is looking up contributor_basis_name_bases. Why is adding basis between contributor and name_bases? How can I get it to stop?
Ok, it's not a answer about why rails is adding 'basis' but it will work for you.
Use set_table_name 'contributor_name_bases' in your model.
Related
I'm trying to manually add data to a table in rails using the rails console, but I keep getting a undefined local variable or method error.
The model is namespaced under ratings:
models/ratings/value_for_money_score.rb
class Ratings::ValueForMoneyScore < ApplicationRecord
end
To try and manually add a record to the database, I run the following in the console:
$ RatingsValueForMoneyScore.create(score: '1', description:"Terrible, definitely not worth what was paid!")
And I get this error: NameError: uninitialized constant RatingsValueForMoneyScore
I have tried a few different versions such as
RatingsValueForMoneyScores.create,
Ratings_ValueForMoneyScores.create,
ratings_value_for_money_scores.create but keep getting the same error. What am I doing wrong?
Try
::ValueForMoneyScore.create(score: '1', description:"Terrible, definitely not worth what was paid!")
The error is descriptive enough in this case, the class RatingsValueForMoneyScore pretty much doesn't exist. Check your namespace, you have a class name (which should be singular) Rating, and the module ValueForMoneyScore. You'd use either
(after renaming the class to Rating)
Rating.create(...)
or
ValueForMoneyScores.create(...)
Your syntax is equivalent to:
class Rating
module ValueForMoneyScores < ApplicationRecord
...
end
end
The answer was a combination of input, so collecting that in one answer.
My namespaces weren't properly set up (I was using "Ratings" rather than "Rating"), so I fixed this for the tables. My models then looked as follows:
models/rating.rb
class Rating < ApplicationRecord
end
models/rating/value_for_money_score.rb
class Rating::ValueForMoneyScore < ApplicationRecord
end
And then this command worked for creating records in the rating_value_for_money_score table
$ Rating::ValueForMoneyScore.create(score: '1', description: "Test")
In my Rails I have the following models:
A STI sub-class
class Subscription::Discount < Subscription
def self.new_with_url
...
end
end
and another model class (doing completely different things, this is a STI base class)
class Discount < ActiveRecord::Base
end
So in my controller, I uses Subscription::Discount when I create users:
#user.subscription = ::Subscription::Discount.new_with_url()
However it complains: undefined method 'new_with_url' for #<Class:0x007fbb499c6740>
I think Rails is not calling the right class with new_with_url. On top of that I am not sure what #<Class:0x007fbb499c6740> is. So, two questions:
Without renaming any model, how can I reference Subscription::Discount properly?
Why is the error message saying #<Class:0x007fbb499c6740>, I can understand if it is Discount instead of that anonymous class.
EDIT:
Here are all the relevant models:
app/model/discount.rb
app/model/coffee_discount.rb (CoffeeDiscount < Discount)
app/model/subscription.rb
app/model/subscription/discount.rb (Subscription::Discount < Subscription)
The method is named create_with_url but you're calling new_with_url.
Fix the method name.
I'm using ruby and activerecord to get information about a mysql table.
I was hoping I could get this information directly from my model class, is this possible?
Say I have my model:
class Product < ActiveRecord::Base
end
Is it now possible for me to get information regarding:
1. mysql table
2. columns
3. column types
Or do I have to look somewhere deeper into the ActiveRecord module to get this?
Product.table_name
Product.column_names
Product.columns_hash['title'].type
Have a look at ActiveRecord::ModelSchema::ClassMethods:
class Product < ActiveRecord::Base
self.table_name # 1
self.columns # 2
self.columns_hash['name'].type # 3
end
I want to use a column called type without invoking Single Table Inheritance (STI) - I just want type to be a normal column that holds a String.
How can I do this without having Rails expecting me to have single table inheritance and throwing an exception of The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.?
Any ideas on how to do this?
In Rails 3.1 set_inheritance_column is deprecated, also you can just use nil as a name, like this:
class Pancakes < ActiveRecord::Base
self.inheritance_column = nil
#...
end
You can override the STI column name using set_inheritance_column:
class Pancakes < ActiveRecord::Base
set_inheritance_column 'something_you_will_not_use'
#...
end
So pick some column name that you won't use for anything and feed that to set_inheritance_column.
In newer versions of Rails you'd set inheritance_column to nil:
class Pancakes < ActiveRecord::Base
self.inheritance_column = nil
#...
end
I know this question is rather old and this deviates a bit from the question you are asking, but what I always do whenever I feel the urge to name a column type or something_type is I search for a synonym of type and use that instead:
Here are a couple alternatives: kind, sort, variety, category, set, genre, species, order etc.
Rails 4.x
I encountered the problem in a Rails 4 app, but in Rails 4 the set_inheritance_column method does not exist at all so you can't use it.
The solution that worked for me was to disable the single table inheritance by overriding ActiveRecord’s inheritance_column method, like this:
class MyModel < ActiveRecord::Base
private
def self.inheritance_column
nil
end
end
Hope it helps!
If you want to do this for all models, you can stick this in an initializer.
ActiveSupport.on_load(:active_record) do
class ::ActiveRecord::Base
# disable STI to allow columns named "type"
self.inheritance_column = :_type_disabled
end
end
I'm using a tool(UltraSms) that required three tables named (smsin, smsout & smsparts)
I need these tables to be used in the same Rails application that has other tables. With ActiveRecrod I know that table names has to be plural of the Active record class name by convention. Is there a way to map those to an ActiveRecrod class easily or should I find manual way to do ORM for it?
Thanks,
Tam
Seems that in Rails3.1 , the method name changed to table_name=, e.g.
class Mouse < ActiveRecord::Base
self.table_name = "mice"
end
You can do this:
class MyClass < ActiveRecord::Base
set_table_name "smsin"
end