I'm trying to access helper methods inside my migrations. I can't seem to get anything to work when accomplishing something like this:
Migration File:
require File.expand_path('lib/migration_helper')
include MigrationHelper
class NewTable < ActiveRecord::Migration
def change
create_table :new_table do |t|
t.boolean :boolean
safe_delete_methods
end
end
end
Migration helper in /lib directory
#Custom Methods available to Migrations
module MigrationHelper
def safe_delete_methods
return
t.boolean :deleted, :default => 0, :null => false
t.integer :deleted_by, :default => 0, :null => false
t.datetime :deleted_at
end
end
Thank you for any answers
module MigrationHelper
def safe_delete_methods
t.boolean :deleted, :default => 0, :null => false
t.integer :deleted_by, :default => 0, :null => false
t.datetime :deleted_at
end
end
cann't use return before the code.
Related
I'm working through a Rails tutorial, and have hit a wall I'm not sure if I missed a step. I have two models, both with a boolean called 'visible', but I can only select using it on one of the models. For reference here are my migrations
class CreateSubjects < ActiveRecord::Migration
def up
create_table :subjects do |t|
t.string "name"
t.integer "position"
t.boolean "visible", :default => false
t.timestamps null: false
end
end
def down
drop_table :subjects
end
end
And
class CreatePages < ActiveRecord::Migration
def up
create_table :pages do |t|
t.integer "subject_id"
t.string "name"
t.string "permalink"
t.integer "position"
t.boolean "visible", :default => false
t.timestamps null: false
end
add_index("pages", "subject_id")
add_index("pages", "permalink")
end
def down
drop_table :pages
end
end
Both have a t.boolean "visible", :default => false in them. And I can edit them and change that value fine. But if I say pull up a rails console and try...
This works fine:
Subject.visible
This gives me a NoMethodError: undefined method `visible':
Page.visible
During one point in the tutorial I had to change the line
#page.sections.visible.sorted.each
to
#page.sections.where(:visible => true).sorted.each
Which did work, but I have no idea WHY I had to do so
Link to project on GitHub if it helps
https://github.com/TaylorHuston/Rails_LyndaCMS
The visible function is an instance function, so you have to use it on an instance of Page:
Page.new.visible
You were able to use it on Subject because you created a scope :visible, so you have one function for the instance and one for the Relation.
I have something like the following code. (Model names changed as they're not important to what's happening.)
The #find_or_create_bar_for_blah_id works fine most of the time. Occasionally it will return nil though and I'm not sure why.
It's some kind of race condition as the problem happens in resque jobs that run as part of our app.
Any clues as to how #find_or_create_bar_for_blah_id could return nil?
class Foo < ActiveRecord::Base
has_many :bars, :dependent => :destroy
def find_or_create_bar_for_blah_id(locale_id)
begin
bars.where(:blah_id => blah_id).first || bars.create!(:blah_id => blah_id)
rescue ActiveRecord::RecordNotUnique
bars.where(:blah_id => blah_id).first
end
end
end
class Bar < ActiveRecord::Base
belongs_to :foo
validates_uniqueness_of :blah_id, :scope => :foo_id
end
# db/schema.rb
create_table "bars", :force => true do |t|
t.integer "foo_id"
t.integer "blah_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "bars", ["foo_id", "blah_id"], :name => "index_bars_on_foo_id_and_blah_id", :unique => true
add_index "bars", ["foo_id"], :name => "index_bars_on_foo_id"
create_table "foos", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "foos", ["name"], :name => "index_foos_on_name"
Doh! This was because we were using update_attribute in part of the code, which of course doesn't run AR validations. embarrassed face
I'm using the composite primary keys gem from drnic and I've got a problem with it:
If I want to create a CourseOrder (with has a cpk) with the following command in my tests: course_order = CourseOrder.new(:daily_order => daily_orders(:daily_order_one_of_today_for_hans),:course => courses(:non_veg_2), :finished => false, :ordered_at => Time.now) I'll get the following error:
ActiveRecord::StatementInvalid: PGError: ERROR: null value in column "course_iddaily_order_id" violates not-null constraint
: INSERT INTO "course_orders" ("course_iddaily_order_id", "course_id", "ordered_at", "finished", "daily_order_id") VALUES (NULL, 489519433, '2011-03-01 10:19:27.169397', 'f', 594369222) RETURNING "course_iddaily_order_id"
I think that there is a course_iddaily_order_id is wrong, isn't it?
My Migration file looks like this:
class AddCourseOrder < ActiveRecord::Migration
def self.up
create_table :course_orders, :primary_key => [:course_id, :daily_order_id] do |table|
table.integer :course_id
table.integer :daily_order_id
table.datetime :ordered_at, :null => false
table.boolean :finished, :default => false, :null => false
end
end
def self.down
drop_table :course_orders
end
end
The resulting schema part looks like this:
create_table "course_orders", :primary_key => "course_iddaily_order_id", :force => true do |t|
t.integer "course_id", :null => false
t.integer "daily_order_id", :null => false
t.datetime "ordered_at", :null => false
t.boolean "finished", :default => false, :null => false
end
My Model looks like this:
class CourseOrder < ActiveRecord::Base
set_primary_keys :course_id, :daily_order_id
belongs_to :course
belongs_to :daily_order
end
I don't know whats wrong here, can you help?
I guess the create_table method doesn't takes an array for :primary_key option. I guess you can omit setting it.
I just set up a new migration and model relationships, and in console when testing the relationship between tables I get the following error: NameError: uninitialized constant.
Does anyone have any idea what is wrong?
Thank you
Edit:
Here's the error
NameError: uninitialized constant Profile::ProfileNotification
from C:/Ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:105:in `const_missing'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2199:in `compute_type'
from C:/Ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/kernel/reporting.rb:11:in `silence_warnings'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2195:in `compute_type'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:156:in `send'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:156:in `klass'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:187:in `quoted_table_name'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/has_many_association.rb:97:in `construct_sql'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:21:in `initialize'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1300:in `new'
from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1300:in `profile_notifications'
from (irb):3
Code from the ProfileNotification migration:
class CreateProfileNotifications < ActiveRecord::Migration
def self.up
create_table :profile_notifications do |t|
t.integer :profile_id, :null => false
t.integer :notification_id, :null => false
t.string :notification_text
t.boolean :checked, :default => false
t.boolean :update_reply, :default => false
t.boolean :opinion_reply, :default => false
t.boolean :message_reply, :default => false
t.boolean :pm, :default => false
t.boolean :accepted_friend, :default => false
t.boolean :accepted_supporter, :default => false
t.timestamps
end
end
def self.down
drop_table :profile_notifications
end
end
Well, I figured out the problem. When I was running ruby script/generate model, I was typing ruby script/generate model ProfileNotifications. When I typed ruby script/generate model ProfileNotification (singular) it worked. Naming conventions kill me. Thanks for all the help.
It's breaking because you're referencing Profile::ProfileNotification which doesn't exist.
Rails considers this a model named ProfileNotification located in the Profile namespace, but your comment suggests that Profile is another model class and not a namespace.
Based on the migration you have posted, I think you're confused about the Rails naming convention for one-to-many relationships. Here's how I think it's supposed to look:
class CreateNotifications < ActiveRecord::Migration
def self.up
create_table :notifications do |t|
t.references :profile
t.text :body
t.boolean :checked, :default => false
t.boolean :update_reply, :default => false
t.boolean :opinion_reply, :default => false
t.boolean :message_reply, :default => false
t.boolean :pm, :default => false
t.boolean :accepted_friend, :default => false
t.boolean :accepted_supporter, :default => false
t.timestamps
end
end
def self.down
drop_table :notifications
end
end
class Profile < ActiveRecord::Base
has_many :notifications
end
class Notification < ActiveRecord::Base
belongs_to :profile
end
Now when you execute Profile.find(1).notifications you should get a list of the associated notifications to that profile.
More information: Active Record Associations
I'm trying to understand the new arel engine in Rails 3 and I've got a question.
I've got two models, User and Task
class User < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :user
end
here is my routes to imply the relation:
resources :users do
resources :tasks
end
and here is my Tasks controller:
class TasksController < ApplicationController
before_filter :load_user
def new
#task = #user.tasks.new
end
private
def load_user
#user = User.where(:id => params[:user_id])
end
end
Problem is, I get the following error when I try to invoke the new action:
NoMethodError: undefined method `tasks' for #<ActiveRecord::Relation:0x3dc2488>
I am sure my problem is with the new arel engine, does anybody understand what I'm doing wrong?
Sorry guys, here is my schema.db file:
ActiveRecord::Schema.define(:version => 20100525021007) do
create_table "tasks", :force => true do |t|
t.string "name"
t.integer "estimated_time"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.string "remember_token"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
add_index "users", ["username"], :name => "index_users_on_username", :unique => true
end
I believe you want:
def load_user
#user = User.where(:id => params[:user_id]).first
end
Until you ask for a record it will stay a relation.
But find(params[:user_id]) will still work and return the record.
Does it work if you change your load_user method as shown below?
def load_user
#user = User.find(params[:user_id])
end
Also, I think you might need to change your new action to:
def new
#task = #user.tasks.build
end
Don't confuse the Arel gem's interface with the new ActiveRecord query interface. The syntax described here will not work: http://github.com/brynary/arel
ActiveRecord uses Arel under the hood but creates its own Arel-like API. Here's a brief look at the new ActiveRecord query interface: http://m.onkey.org/2010/1/22/active-record-query-interface
It's actually pretty simple. Here is one method...
def new
#task = #user.tasks.new
end
private
def load_user
# you must call a non-deferred operator to actually return
# the tuple that is connected to your tasks
#user = User.where(:id => params[:user_id]).first
end
Be sure to take a look at the seven part learning series I am doing on Active Relation. The first episode will help you understand what your error was more clearly. http://Innovative-Studios.com/#pilot
find() IS NOT deprecated in some instances as stated before. I would limit the use of find() for atomic values (where you are searching for a specific item/index) Anything that could possibly be collection based I would stick to the Where (restriction) clause wrapper in ActiveRecord for Arel.