I have a simple Rails application I'm using to try and learn Rails.
It has a database table I create like this using ActiveRecord:
class CreateMovies < ActiveRecord::Migration
def up
create_table :movies do |t|
t.string :title
t.string :rating
t.text :description
t.datetime :release_date
t.timestamps
end
end
def down
drop_table :movies
end
end
Here is my corresponding model class:
class Movie < ActiveRecord::Base
def self.all_ratings
%w(G PG PG-13 NC-17 R)
end
def name_with_rating()
return "#{#title} (#{#rating})"
end
end
When I call name_with_rating on an instance of Movie, all it returns is " ()" for any Movie. What is the correct syntax or method to call to get at the fields of the Movie instance from within an instance method of Movie?
Please note that the database has been properly populated with movie rows, etc. I've done rake db:create, rake db:migrate etc.
Active record attributes aren't implemented as instance variables. Try
class Movie < ActiveRecord::Base
def name_with_rating()
return "#{title} (#{rating})"
end
end
class Movie < ActiveRecord::Base
def name_with_rating
"#{title} (#{rating})"
end
end
then in the console Movie.first.name_with_rating should work.
Related
I need some help here. I have a community model with belongs to an account. I use devise for the authentication stuff. Now the issue is when I try to submit/create a community I get this error 'undefined method `account_id=' for #Community:0x00007febf2e806f8 Did you mean? account='
controller
def create
#community = Community.new comunity_values
#community.account_id = current_account.id
if #community.save
redirect_to community_path
else
render :new
end
end
private
def comunity_values
params.require(:community).permit(:name, :url,:rules)
end
end
model
class Community <ApplicationRecord
belongs_to :account
validates_presence_of :url, :name , :rules
end
migrations
class CreateCommunities < ActiveRecord::Migration[6.0]
def change
create_table :communities do |t|
t.references :account
t.string :name
t.string :url
t.text :rules
t.string :total_members
t.timestamps
end
end
end
In model account you have to put the reference to communities model too. Something like:
has_many :community
Other think you have to know, is that you don't need to specify the id when you create using relations, you could use in a more readable way:
#community.account = current_account
#community.save
And I think that you are inverting the order of things, because one account has many communities so... You could do that as follows:
current_account.community.create!(comunity_values)
Hope this helps
This is not a duplicate of 'How do I explicitly specify a Model's table-name mapping in Rails?', as I am looking for a way to not explicitly set the table names. Instead I want to automatically set the table names accordingly to the inheritance of a model.
I've got the following model structure:
models
First (inheritance)
Second (inheritance)
Third (model)
User (model)
Second (model)
I have the following tables in the database:
first_second_thirds
users
user_seconds
When I execute the following code:
First::Second::Third.create(id: 1)
User.create(id: 1)
User::Second.create(id: 1)
I get that error:
ActiveRecord::StatementInvalid: Could not find table 'thirds'
How do I tell the model the appropriate database table?
EDIT: Adding Code Examples
db/migrate/20170305200503_create_first_second_third.rb
class CreateFirstSecondThirds < ActiveRecord::Migration[5.0]
def change
create_table :first_second_thirds do |t|
t.timestamps
end
end
end
db/migrate/20161114164114_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.timestamps
end
end
end
db/migrate/20170305145804_create_user_stories.rb
class CreateUserSeconds < ActiveRecord::Migration[5.0]
def change
create_table :user_seconds do |t|
t.timestamps
end
end
end
app/models/first/second/third.rb
class User < ApplicationRecord
end
app/models/user.rb
class User < ApplicationRecord
end
app/models/user/second.rb
class User < ApplicationRecord
end
I have a model called categories currently they belong to product but I'd like them to belong to store instead. I have several thousand of these so what I'd like to do is create a migration that adds a store_id to categories and then, gets the associated product.store.id from it's current association and adds that to the store_id. After that I'd like to remove the product association.
Does anybody know how to easily and safely achieve that?
Should you add the association in the wrong direction, you can use change_table to reverse the association:
class CreateFavorites < ActiveRecord::Migration[5.0]
def change
create_table :favorites do |t|
t.belongs_to :article
t.timestamps
end
end
end
class RemoveArticleFromFavorites < ActiveRecord::Migration[5.0]
def change
change_table :favorites do |t|
t.remove_references :article
end
end
end
class AddFavoriteToArticles < ActiveRecord::Migration[5.0]
def change
change_table :article do |t|
t.belongs_to :favorite
end
end
end
First rename column to store_id,
rename_column :categories, :product_id, :store_id
Then change the assosciation.
Now you can either write a rake task to transfer the data or you can manually do it via console.
It's better way to write a rake task.
According to your requirement your rake task can be, get the store from the product and assign to the category according to your requirement.
require 'rake'
namespace :category do
task :product_to_store => :environment do
Category.all.each do |category|
product = Product.find(category.store_id) //you will get product,as now it chnaged to store_id
if product.present?
category.store_id = product.try(:store).try(:id) //assign the product's store_id to the category, use try to reject errored records
category.save
end
end
end
end
Now run, **`rake category:product_to_store`**, thats it, the data gets transfered.
You can just add new migration that will create the new reference with categories as store.
class YourMigrationName < ActiveRecord::Migration
def up
add_reference :categories, :store, index: true
Category.all.each do |category|
category.store_id = category.product_id
category.save
end
remove_column :product_id
end
def down
add_reference :categories, :product, index: true
Category.all.each do |category|
category.product_id = category.store_id
category.save
end
remove_reference :categories, :store, index: true
end
end
May be if you have added the product reference and index then write the same as the store so then it will delete the index as well.
you have data in the column you don't want to lose, then use rename_column
I've had some experience with some self projects in Rails and I'm having some trouble creating the data model for this specific scenario. Basically, there are many users, each of whom can play many instruments, and for each user/instrument pairing, there is a certain skill level associated with it.
For example, Joe can play saxophone with skill level 5, clarinet with skill level 2, and trumpet with skill level 3. Bob can play trombone with skill level 1, saxophone with skill level 4, and clarinet with skill level 5.
I understand how to make this with traditional SQL, but I really want to be able to take advantage of the Rails ActiveRecord features (so, in theory, I could do something like this:
#users = User.all
#users.each do |user|
user.instruments do |ins|
puts ins.level #The current user's skill level on a particular instrument
end
end
How do I create the migrations/models to achieve this? Thanks!
the models are basically:
class User < ActiveRecord::Base
has_many :instrument_skills
has_many :instruments, through: :instrument_skills
end
class InstrumentSkill < ActiveRecord::Base
belongs_to :instrument
end
class Instrument < ActiveRecord::Base
end
that said you could create the models like::
rails g model User name:string
rails g model InstrumentSkill instrument_id:integer user_id:integer level:integer
rails g model Instrument name:string
then your generated migration probably look like:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class CreateInstruments < ActiveRecord::Migration
def change
create_table :instruments do |t|
t.string :name
t.timestamps
end
end
end
class CreateInstrumentSkills < ActiveRecord::Migration
def change
create_table :instrument_skills do |t|
t.integer :user_id
t.integer :instrument_id
t.integer :level
t.timestamps
end
end
end
I am trying to create a task management prototype. I created two models - Category and Task, while tasks belong to category and a category can contain many tasks.
class Category < ActiveRecord::Base
has_many :tasks
end
And
class Task < ActiveRecord::Base
belongs_to :category
end
Then in migration file
class CreateTasks < ActiveRecord::Migration
def change
create_table :tasks do |t|
t.string :name
t.string :note
t.references :category
t.timestamps null: false
end
end
end
and
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.string :description
t.timestamps null: false
end
end
end
I tried to seed some data to start working with, here's the seed file
c1 = Category.create(name: 'Category1')
Task.create(name: 'TASK1', category_id: c1.id)
However it gives me the error:
rake db:seed
rake aborted!
ActiveRecord::UnknownAttributeError: unknown attribute 'category_id' for Task.
I have tried the following as well
Task.create(name: 'TASK1', category: c1)
Task.create(name: 'TASK1', category: c1.id)
And I got the error
rake db:seed
rake aborted!
ActiveRecord::AssociationTypeMismatch: Category(#70174570341620) expected, got Fixnum(#70174565126780)
However in the browser, #category.id does load and display (as a two digit number 33).
Think I might be missing something obvious but can't figure out why I can't create the task associated with the specific category c1 in from the seeding the data
just need to pass the object:
c1 = Category.find_or_create_by(name: 'Category1')
I recommend to use find_or_create_by for not create twice the same data
Task.find_or_create_by(name: 'TASK1', category: c1)
if not work try create the same data in the console
I hope help you