I'm on Windows XP...
Ruby 1.9.2
Rails 3.0.9
MS SQL Server 2005
I'm using tiny_tds + activerecord-sqlserver-adapter
In my database I have table named t4.
I have created a model like this: rails generate model t4
Here is my simple model t4.rb:
class T4 < ActiveRecord::Base
end
Here is migration file 20111013125957_create_t4s.rb:
class CreateT4s < ActiveRecord::Migration
def self.up
create_table :t4s do |t|
t.timestamps
end
end
def self.down
drop_table :t4s
end
end
I have schema.rb:
...
create_table "t4", :force => true do |t|
t.string "title", :limit => 50
end
...
Problem:
When I try T4.select("title").where(["id = 3"]) I get error message:
ActiveRecord::StatementInvalid: TinyTds::Error: Invalid object name 't4s'.: SELECT title FROM [t4s] WHERE (id = 3)
P.S.:
I have another some tables named Adddocs and Eclaims.
There are not problems with queries to them.
I guess that problem is that T4.select("title").where(["id = 3"]) maps to SELECT title FROM [t4s] WHERE (id = 3) (T4 to t4s).
Why? I don't know
But when I edited file config/initializers/inflections.rb like this:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 't4', 't4'
end
Everything works! But it's not suitable solution (bad tone i think) :(((
By convention, if you create a model named album, rails will create a table called albums.
To override this (which isn't usually done) and use a custom defined table name you can use set_table_name method like this in your model:
class Album < ActiveRecord::Base
self.table_name="album" * define here whatever table name you have
end
When you create a new model it is the singular of the object your storing, whereas when it then generates the table, it uses the plural as there are multiple stored within the table. Example...
If you create a model named user, you'll end up with app/models/user.rb but the table it makes will be called users.
If you don't like that you have a few options...
You can override the inflections as you've done, however you should only do this if Rails is getting the pluralization wrong, rather than forcing it to use a certain word.
You can override the table name using the set_table_name method in the model file, providing it with a parameter of what your table name actually is.
You could disable the whole pluralized table names with config.active_record.pluralize_table_names = false in your config/application.rb file, however I strongly recommend you don't do this.
Ultimately I would suggest using more descriptive table names which can be pluralized over ones that can't. T4 as a model and table name don't explain to me what's stored within, where as Post does.
Related
Original code looks like this:
# app/models/sso_configuration.rb
class SsoConfiguration < ActiveRecord::Base
end
# db/schema.rb
create_table "sso_configurations", force: true do |t|
...
end
I have to rename the model and add namespace so that I'll have Sso::SamlConfiguration. I changed model and database table.
# db/migrate20160225144615_rename_sso_configurations_to_sso_saml_configurations.rb
class RenameSsoConfigurationsToSsoSamlConfigurations < ActiveRecord::Migration
def change
rename_table :sso_configurations, :sso_saml_configurations
end
end
# db/schema.rb
create_table "sso_saml_configurations", force: true do |t|
...
end
# app/models/sso/saml_configuration.rb
module Sso
class SamlConfiguration < ActiveRecord::Base
end
end
When I open my rails console, the following happens.
> Sso::SamlConfiguration
=> Sso::SamlConfiguration(Table doesn't exist)
> Sso::SamlConfiguration.new
=> PG::UndefinedTable: ERROR: relation "saml_configurations" does not exist
My original thinking was that namespaced models should, by convention, have the snakecase name as the table name such that Foo::Bar should have a corresponding foo_bars table. Am I missing something with my setup?
rename_table :sso_configurations, :sso_saml_configurations
would imply this SsoSamlConfiguration.all when your trying to do this Sso::SamlConfiguration.all
Simply rollback your migration and change this line
rename_table :sso_configurations, :sso_saml_configurations
to this
rename_table :sso_configurations, :saml_configurations
and now this should work
Sso::SamlConfiguration.all
PG::UndefinedTable: ERROR: relation "saml_configurations" does not
exist
Rails by default looks for the table whose name is plural name of model i.e, in your case it looks for saml_configurations as the model name is saml_configuration.
You need to explicitly map the model to a different table by using self.table_name
# app/models/sso/saml_configuration.rb
module Sso
class SamlConfiguration < ActiveRecord::Base
self.table_name = "sso_saml_configurations"
end
end
I figured out the solution by copying what rails would do if I let it generate a namespaced model for me
rails g model sso/test
invoke active_record
create db/migrate/20160226074853_create_sso_tests.rb
create app/models/sso/test.rb
create app/models/sso.rb
invoke rspec
create spec/models/sso/test_spec.rb
invoke factory_girl
create spec/factories/sso_tests.rb
I checked all the path and name conventions in these new files and the only one I missed was the file app/models/sso.rb.
Creating the following solved my problem:
# app/models/sso.rb
module Sso
def self.table_name_prefix
'sso_'
end
end
Then
rails d model sso/test
rails generate model product name:string twoWord:string twoWordRef:references
produces the following migration file
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.string :twoWord
t.references :twoWordRef, index: true
t.timestamps null: false
end
add_foreign_key :products, :twoWordRefs
end
end
I thought that field names were supposed to be snake case, not camel case, yet rails generate model is producing camel case field names in the migration file. I think I am following the examples on my generate command.
I am also finding issues later on when I try to update via reference where rails assumes the foreign key is in snake case and can't find my foreign key in the table.
What am I doing wrong? Thanks
Rails automatically generate the database tables in snake case. For example if your model is TestModel corresponding table in database will be test_models. However same is not the case for attributes.
Do this instead:
rails generate model product name:string two_word:string two_word_ref:references
Update
This is completely out of scope for what OP asked, but I thought sharing this might be helpful if you are starting Rails. Rails uses a few conventions when naming models and tables (like singular name for model and plural for table). For this it uses ActiveSupport::Inflector module.
The Inflector transforms words from singular to plural, class names to
table names, modularized class names to ones without, and class names
to foreign keys. The default inflections for pluralization,
singularization, and uncountable words are kept in inflections.rb.
You can use its classify and tableize methods to validate corresponding names. Eg:
"test_models".classify
# => "TestModel"
"TestModel".tableize
# => "test_models"
I need to generate a migration that creates a table called creditcardquotas, but rails generate a table called credit_card_quota exactly like the name of the model.
I tried with the method pluralize
helper.pluralize(2, 'quota')
=> "2 quota"
class CreateCreditCardQuota < ActiveRecord::Migration
def change
create_table :credit_card_quota do |t|
t.integer :credit_card_id
t.integer :quotes
t.integer :interest
t.timestamps
end
end
end
How do I tell Rails migration that I want that the table called credit_card_quotas?
Create a file in config/initializers/. Name that file inflections.rb and add this content in it.
Before adding you get:
helper.pluralize(2, 'quota')
=> "2 quota"
Add the inflection:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'quota', 'quotas'
end
After that:
helper.pluralize(2, 'quota')
=> "2 quotas"
You can add any kind of valid or invalid pluralizations in this file...
Run the migrations after having applied this configuration change.
In my recent experience, it seems like rails/active record does not know how to pluralize the word "quota", or that it thinks that the plural of the word "quota" is "quota". I just tried to create a new migration for a "quotas" table that was paired with a Quota class in quota.rb. In rails console, when trying to use this model, I saw this warning:
Quota(Table doesn't exist)
But when I updated my Quota class to be Quotas and renamed the file, I was able to use the quotas table in the db. My eventual solution was to change the db table name from quotas to quota and use the Quota class for my model.
I have a new Rails 4 app where I created a few models in the STI configuration.
The main model is called Order and it inherits from ActiveRecord::Base. This is how it looks like:
class Order < ActiveRecord::Base
TYPES = %w(remote local)
scope :remotes, -> { where(type: 'remote') }
scope :locals, -> { where(type: 'local') }
end
The other two models are within a folder in models/orders and they're called Remote and Local and they both inherit from Order
The orders migration file looks like this:
def change
create_table :orders do |t|
t.string :source_url, null: false
t.string :final_url, null: false
t.string :type
t.string :category
t.timestamps
end
end
I also made sure I was including the models/orders dir into Rails, by doing:
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
Now, when I log into the console with an emptied DB and run Order.all everything is fine and I get an empty relation object. But after I create the first Remote object and try running Order.all again I get the following error:
>> Order.all
Order Load (1.0ms) SELECT "orders".* FROM "orders"
ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate
the subclass: 'Remote'. This error is raised because the column 'type' is reserved
for storing the class in case of inheritance. Please rename this column if you didn't
intend it to be used for storing the inheritance class or overwrite
Order.inheritance_column to use another column for that information.
What is going on here? What have I done wrong?
Thanks in advance.
In order to debug this, I'd simply and see what I learn from one of two experiments...
First, even just temporarily, move the subclasses out of the Orders folder. It may be that you have them nested in a Module, or that rails expects them to be based on the name, so the 'type' column doesn't match what you think it should.
second, I'd try creating one of the subclasses from the command line, persisting it, and seeing what ActiveRecord puts in that type column and see if it matches what you're expecting.
I suspect this has something to do with the subfolder under models and Rails' inability to find the class as the type is specifying it.
Column name 'type' is restricted in ActiveRecord. try renaming the column name to something else or if you can't try this:
self.inheritance_column = :_type_disabled
I had this same issue when I used type as a column name, maybe try renaming your column name to something else?
I want to create a model 'Relation' which extends ActiveRecord::Base, set it's table name as 'questions_tags', and without primary key. What should I do?
class Relation < ActiveRecord::Base
set_table_name 'questions_tags' # set table name, right?
# how to define 'no-pk'?
end
UPDATE
I know use 'create_table' can solve this problem, but this is just what I want to know: What is the magic behind create_table(:id=>false)? How can I get the same effect without using create_table(:id=>false)?
Create a migration that looks like this:
class CreateQuestionsTags < ActiveRecord::Migration
def self.up
create_table :questions_tags, {:id => false, :force => true} do |t|
...
t.timestamps
end
end
def self.down
drop_table :questions_tags
end
end
If you're looking to create a pivot table, as it looks like from the table name, then AR will handle that in the background.
However, if you're looking to create a table with more feilds then:
1) rename your table to "realtions" please
2) use a primary key "id"
There's no good reason not to be using a primary key in a table, and it is very likely that you might well find yourself regretting it later.
Why don't you want a PK?
Active Record expects a PK, and I don't see what harm it can do.