Ruby on Rails migration stuck - ruby-on-rails-4

I'm new to Ruby on Rails and would be grateful for some help with migrations.
Version 4
first migration
class CreateRooms < ActiveRecord::Migration
def change
create_table :rooms do |t|
t.integer :legacy_id, null: true
t.string :tag, null: false
t.string :name_en, null: false
t.string :name_et, null: false
t.string :name_ru, null: false
t.string :color, default: 'Black'
t.timestamp :enabled_from, default: 0
t.timestamp :enabled_to, default: 0
t.timestamps null: false
end
add_index :rooms, :tag, unique: true
add_index :rooms, :name_en, unique: true
add_index :rooms, :name_et, unique: true
add_index :rooms, :name_ru, unique: true
end
end
next one
class AddDefaultValuesToRoom < ActiveRecord::Migration
def change
add_column :rooms, :priority, :integer, null: false
change_column :rooms, :enabled_from, :datetime, default: '2008-08-15'
change_column :rooms, :enabled_to, :datetime, default: '2050-12-31'
add_index :rooms, :priority, unique: true
end
end
Strangely enough this is not reflected in schema
create_table "rooms", force: :cascade do |t|
t.integer "legacy_id"
t.string "tag", null: false
t.string "name_en", null: false
t.string "name_et", null: false
t.string "name_ru", null: false
t.string "color", default: "Black"
t.datetime "enabled_from", default: '2008-08-15 00:00:00'
t.datetime "enabled_to", default: '2050-12-31 00:00:00'
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "rooms", ["name_en"], name: "index_rooms_on_name_en", unique: true
add_index "rooms", ["name_et"], name: "index_rooms_on_name_et", unique: true
add_index "rooms", ["name_ru"], name: "index_rooms_on_name_ru", unique: true
add_index "rooms", ["tag"], name: "index_rooms_on_tag", unique: true
rake db:rollback crashes
rake db:rollback STEP=2 --trace
** Invoke db:rollback (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:rollback
ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
Migrating to AddDefaultValuesToRoom (20160127121254)
(0.1ms) begin transaction
== 20160127121254 AddDefaultValuesToRoom: reverting ===========================
(0.1ms) rollback transaction
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
ActiveRecord::IrreversibleMigration/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.2/lib/active_record/migration/command_recorder.rb:65:in `inverse_of'
Now I'm in a fix, could somebody help me out ?
TIA
Pavel

change_column creates an irreversible change to your database, which means you can't roll it back. See the guide: http://guides.rubyonrails.org/active_record_migrations.html#changing-columns
The idea here is that reverting your data would result in data loss, so Rails prevents you from doing something destructive by default and throws an error to stop the process.
Change your last migration to utilize reversible or up/down methods, in order to explicitly tell Rails how to reverse your change (note that you will lose any data stored in the new column priority). See: http://guides.rubyonrails.org/active_record_migrations.html#using-reversible
Here's an example using up/down methods:
class AddDefaultValuesToRoom < ActiveRecord::Migration
def up
add_column :rooms, :priority, :integer, null: false
change_column :rooms, :enabled_from, :datetime, default: '2008-08-15'
change_column :rooms, :enabled_to, :datetime, default: '2050-12-31'
add_index :rooms, :priority, unique: true
end
def down
remove_column :rooms, :priority
change_column :rooms, :enabled_from, :datetime, default: 0
change_column :rooms, :enabled_to, :datetime, default: 0
end
end

Related

Accessing database info in rails controller

I'm having trouble defining an amount for a pay action in my item controller. I'm trying to pull in the item price stored in the db. I've tried everything. I reread this, http://guides.rubyonrails.org/action_controller_overview.html, and still no luck.
In items controller:
def pay
# Find the user to pay.
user = User.find( params[:id] )
amount = #I have no idea what to put here
fee = 100
If I put in a number it works fine. However when I try to access the item price that is stored in the db, that is when things blow up.
I've tried various definitions:
#item.price #fail
item_price #fail
Item.find (params: [:price]) #fail
Item.price #fail
#EVERYTHING FAILS
Schema:
ActiveRecord::Schema.define(version: 20150127171203) do
create_table "items", force: true do |t|
t.string "name"
t.decimal "price"
t.text "description"
t.integer "booth_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.integer "user_id"
t.string "image"
t.string "image_two"
end
create_table "users", force: true do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.datetime "reset_sent_at"
t.boolean "admin", default: false
t.string "avatar"
t.text "about"
t.string "location"
t.string "publishable_key"
t.string "secret_key"
t.string "stripe_user_id"
t.string "currency"
end
(edit) I also tried defining items in the pay action and that did not help either. 'item = Item.find ( params[:id]'
Does anyone know the right way to do this? I feel like this should be easy but I'm having trouble with it.
Thanks for your consideration and help!
How is a user related to an item? I ask this because if you are using active record, the associations you make in your database will determine the methods that are created for you. Does a user has_many items in your model? Does an item belong_to a user? In which case would be
#user = User.find(1)
and you could find the price like
#item = #user.items.find(1)
#price = #item.price
EDIT
Ok, I took a look at the code you provided here. This example shows a pay method defining a route in the users controller which seems to only be setup to accept a one time fee. In the comments above it, it even says make a one-off payment so we know this is true.
Even in this example here they explicitly say it's for a fixed amount. Now how do we make it dynamic? Well, look at the code. There's some logic in the pay controller isn't there?
You see that Stripe::Charge object being created?
charge = Stripe::Charge.create(
{
amount: amount,
currency: user.currency,
card: params[:token],
description: "Test Charge via Stripe Connect",
application_fee: fee
},
# Use the user-to-be-paid's access token
# to make the charge.
user.secret_key
)
You can move this logic into your item MODEL. Call it pay or something as long as it takes in the user as a parameter.
def pay(user)
amount = self.price
begin
charge = Stripe::Charge.create(
{
amount: amount,
currency: user.currency,
card: user.token,
description: "Test Charge via Stripe Connect",
application_fee: fee
},
# Use the user-to-be-paid's access token
# to make the charge.
user.secret_key
)
flash[:notice] = "Charged successfully! <a target='_blank' rel='connected-account' href='https://dashboard.stripe.com/test/payments/#{charge.id}'>View in dashboard ยป</a>"
rescue Stripe::CardError => e
error = e.json_body[:error][:message]
flash[:error] = "Charge failed! #{error}"
end
end
Then somewhere in your items CONTROLLER define the pay method instead of users like you had before(Make sure you change your routes accordingly). Then call the pay method you just defined, this way you have the price and you can find the user that is currently logged in.
def pay
user = User.find(session[:user_id])
item = Item.find(params[:id])
item.pay(user)
redirect "somewhere"
end

Rails 4 Reflexive Many-to-Many Association

I'm implementing a Rails 4 app that has a Reflexive Many-to-Many Association to represent some MailChimp and HelpScout API parameters.
Some of those parameters have child parameters. Thus, those child parameters have parent parameters (otherwise they couldn't be a child, right?! ;D ).
To implement the reflexive association the two tables below were created
create_table "api_params", force: true do |t|
t.string "name"
t.string "description"
t.string "type"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "nested_params", force: true do |t|
t.integer "parent_param_id"
t.integer "child_param_id"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "nested_params", ["child_param_id"], name: "index_nested_params_on_child_param_id"
add_index "nested_params", ["parent_param_id"], name: "index_nested_params_on_parent_param_id"
What I'd like to have are two methods. One to retrieve a database record's parents and another one to retrieve its children. Below I show you an example.
apiParam = ApiParam.first # retrieving any database record
apiParam.parent_params
# => returns a set of apiParam's parents
apiParam.child_params
# => returns a set of apiParam's children
I read all day long about associations but the examples are always the same. I mean, there is always a class where you define a has_many through and another one where you define a belongs_to but it wasn't enough for what I need.
Thanks in advance. I appreciate any kind of help.
I have your solution (in my case I have the model SyncType):
class SyncType < ActiveRecord::Base
has_and_belongs_to_many(:parents,
:class_name => "SyncType",
:join_table => "sync_type_parents",
:foreign_key => "sync_type_id",
:association_foreign_key => "sync_type_parent_id")
has_and_belongs_to_many(:children,
:class_name => "SyncType",
:join_table => "sync_type_parents",
:foreign_key => "sync_type_parent_id",
:association_foreign_key => "sync_type_id")
end
migration:
create_table "sync_type_parents", :force => true, :id => false do |t|
t.integer "sync_type_id", :null => false
t.integer "sync_type_parent_id", :null => false
end
Enjoy! ;)
I found the answer and I hope it can be helpful for everyone with same kind of problem.
In short, I've got the answer from Ryan Bates' railscasts.com website. More specificly, the answer were found here.
My classes are now as follow:
class NestedParam < ActiveRecord::Base
belongs_to :api_param
belongs_to :child_param, class_name: 'ApiParam'
end
class ApiParam < ActiveRecord::Base
has_many :nested_params
has_many :child_params, :through => :nested_params
has_many :parent_api_params, :class_name => "NestedParam", :foreign_key => "child_param_id"
has_many :parent_params, :through => :parent_api_params, :source => :api_param
end
ActiveRecord::Schema.define(version: 20140910175658) do
create_table "api_params", force: true do |t|
t.string "name"
t.string "description"
t.boolean "required", default: true
t.boolean "struct", default: false
t.string "type"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "nested_params", force: true do |t|
t.integer "api_param_id"
t.integer "child_param_id"
t.boolean "required"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "nested_params", ["api_param_id"], name: "index_nested_params_on_api_param_id"
add_index "nested_params", ["child_param_id"], name: "index_nested_params_on_child_param_id"
end

ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR: column is of type integer[] but default expression is of type integer Rails 4.1.1

I am using Rails 4.1.1 and pg (0.17.1) gem I having error while running the migration
ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR: column "page_ids" is of type integer[] but default expression is of type integer
here is my migration code
class CreatePages < ActiveRecord::Migration
def change
create_table :pages do |t|
t.string :name
t.integer :page_ids, array: true, null: false, default: '{}'
t.timestamps
end
end
end
the array: true not working
Try:
t.integer :page_ids, array: true, null: false, default: []

Rgeo, Mysql and Spatial index error

when trying to run migration to add a spatial index, get
Unknown key: spatial/Users/ME/.rvm/gems/ruby-2.0.0-p353/gems/activesupport-4.0.2/lib/active_support/core_ext/hash/keys.rb:70:in `block in assert_valid_keys'
Using
Ruby 2.0.353
Rails 4.0.2
RGEO 0.3.20
RGEO Active Record 0.4.6
List item
activerecord-mysql2spatial-adapter 0.4.3
Migration Index file looks like
class CreateAddresses < ActiveRecord::Migration
def change
create_table :addresses, :options => 'ENGINE=MyISAM' do |t|
t.string :street_1
t.string :street2
t.string :city
t.string :state
t.string :zip
t.string :country
t.string :full_address
t.column :latlon, :point, :null => false
t.timestamps
end
add_index :addresses, :latlon, :spatial => true
end
end
UPDATE
Corrected this and other errors when I changed the adapter in my database.yml file from mysql2 to mysql2spatial

rails - Data insertion within migration don't work

I'm trying to insert data with migration and don't understand what's wrong with this code:
def change
create_table :sourcebuster_settings do |t|
t.integer :session_length
t.boolean :use_subdomains, default: false
t.string :main_host
t.timestamps
end
Sourcebuster::Setting.create session_length: 30,
use_subdomains: false
end
create_table works fine, but no data inserted after migration. No errors in console.
Previous migrations with the same method of data insertions works fine also. Problem only with this one.
I got it. In my setting model:
before_save { self.main_host = main_host.gsub(/(http:|https:|www\.|:|\/)/,'').downcase if self.main_host }
validates_presence_of :main_host, if: lambda { self.use_subdomains }
validates :main_host, format: { with: VALID_HOST_REGEX }, allow_blank: true
Added allow_blank: true to main_host validation.