I have been at this one for a while and hitting a great wall of fail...
I'm trying to pull some game info from Mochi Media's servers. I have the API hooks in place but when I try to access the file info with Dragonfly I'm getting the following error:
undefined method `file_uid' for #<Game:0x007fba5e0bf188>
Can anyone see anything weird that I'm doing?
Model:
class Game < ActiveRecord::Base
attr_accessible :description, :name, :file, :image
image_accessor :image
image_accessor :file
validates :name, uniqueness: true
validates :name, presence: true
end
Class:
def move(game)
# Grab the mochi game from the queue
mochi_game = Mochi.find(game.id)
if mochi_game
# Setup a new game object
game = Game.new
# Pull the game's name
game.name = mochi_game.name
# Pull the thumb & game file
game.image_url = mochi_game.image_url
game.file_url = mochi_game.file_url
# Pull the metadata
game.description = mochi_game.description
# Save the game to our db
game.save
end
return false
end
Migration:
class AddImageAndGametoGames < ActiveRecord::Migration
def up
add_column :games, :image_uid, :string
add_column :games, :file_uid, :string
end
def down
remove_column :games, :image_uid, :string
remove_column :games, :file_uid, :string
end
end
Looks like once again, in pure Ruby/Rails newbie fashion, I managed to get this wrong. The issue was stemming from a few crazy issues with my DB schema. Once I worked all that out and re-installed the plugin based on an older GIT commit I was able to get this gem up and running.
Hopefully, in some odd way, this helps another SO user who may be interested in trying this Gem.
Related
I have the following model and migration:
class Content::Panels::Iframe < Content::Panel
## Associations ##
belongs_to :panel_holder, polymorphic: true
## Validations ##
validates :uri, presence: true
## Methods ##
def self.plural_name
'iframe_index'
end
end
class AddHeightToIframes < ActiveRecord::Migration[5.1]
def change
add_column :iframes, :height, :integer, after: :headline
end
end
The migration fails as there is no table called 'iframes'. After googling I've tried adding to the iframe class:
self.table_name_prefix = 'content_panels_'
self.table_name = 'content_panels_iframes'
and changing the table title to 'content_panels_iframes', However neither of these work when tried independently or together.
What am I doing wrong? Thanks in advance
When the table name is content_panels_iframes, the migration should be:
add_column :content_panels_iframes, :height, :integer, after: :headline
I am having a problem while validating on an image field in model on a rails4 app.
class ModelA < ActiveRecord::Base
validates :name, presence: true
validates :logo, presence: true
has_attached_file :logo, styles: {
thumb: '100x100>',
square: '200x200#'
}
In the migrations, a new instance of this model is to be created.
def migrate(direction)
super
if direction == :up
obj = Model1.create!(:name => "Test")
This is failing as the required field is not specified and If I am explicitly specifying a default image, then the table does not have the necessary column yet.
This migration runs if I am removing the image (in this case, logo) validation before migration and thereafter specify the image file and details like its name.
Is there a better way to setup this model?
I've figured this out. The problem was in the migrations - the logo migration (as well as validation) was added afterwards of this Object creation in the migration. I added the logo to the Model1.create! and moved this migration After these migrations to solve the error.
Hence, my migrations roughly are:
def change
create_table :... do |t|
t.string :name
t.timestamps
end
Followed by addition of paperclip column
def self.up
change_table :... do |t|
t.attachment :logo
end
end
And added the model in another migration that was coming after them.
def migrate(direction)
super
if direction == :up
logo_img = File.open('app/assets/images/logo-big.png', 'rb')
Model1.create!(:name => "TestObj", :logo => logo_img )
The problem is that I get this error:
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: amenity_id
when I run this code:
task import_amenities: :environment do
agent = Mechanize.new
Kindergarten.find_all_by_public(false).each do |k|
p = agent.get(k.uri)
amenities = p.search("td td tr:nth-child(11) td:nth-child(2)").text.split(/(;|,) */)
amenities.each do |a|
am = Amenity.find_or_create_by_name!("#{a}")
k.update_attributes(amenity_id: am.id)
end
end
end
Kindergartens and Amenities are linked through a HABTM relation and are are defined as below:
kindergarten.rb
class Kindergarten < ActiveRecord::Base
attr_accessible :location, :name, :public, :uri, :address, :contact,
:phone, :url, :email, :description,
:password, :password_confirmation, :amenity_ids
has_and_belongs_to_many :amenities
end
amenity.rb
class Amenity < ActiveRecord::Base
attr_accessible :name, :kindergarten_ids
has_and_belongs_to_many :kindergartens
end
and here's the migration for the join table:
class CreateKindergartensAmenitiesJoinTable < ActiveRecord::Migration
def up
create_table :kindergartens_amenities, :id => false do |t|
t.integer :kindergarten_id
t.integer :amenity_id
end
end
end
The error is caused by this line in the rake task:
k.update_attributes(amenity_id: am.id)
Everything seems to work great in the console until I reach the mass assignment. And I think i am really messing something up here since I've never used before HABTM.
Any thoughts?
I couldn't sleep last night because of this bug but I finally found the solution.
there are a few issues in the code and the first one i noticed once i started digging and adding data in the db manually is that the join table is wrongfully named. Fix for that:
class RenameKindergartensAmenitiesTable < ActiveRecord::Migration
def up
rename_table :kindergartens_amenities, :amenities_kindergartens
end
end
apparently the habtm association is has to have stuff put alphabetically in title. source
Second problem is that I assumed that
k.amenity_id = am.id
would add an amenity_id / kindergarten_id for each amenity existing. In fact k.amenity_id does not mean anything (especially in the case of many ids). The solution that worked is this:
amenities.each do |a|
am = Amenity.find_or_create_by_name!("#{a}")
k.update_attributes(amenity_ids: k.amenity_ids.push(am.id))
end
I haven't modified the attr_accessible anywhere
I just changed my DB from mysql to postgres and I'm getting the following error:
ActionView::Template::Error (PG::Error: ERROR: operator does not exist: character varying = integer
LINE 1: ...ELECT COUNT(*) FROM "agents" WHERE "agents"."client_id" = 1
when doing
client.agents.count
I have a Data is structured as follows: Clients have several Agents, and can only add more Agents if agents.count < X, so I'm using something like client.agents.count to retrieve this value and compare, but I'm getting that error. Do I need to use manual sql to get this done? Or am I missing something stupid?
Thank you for your comments
MODEL INFO
class Agent < User
belongs_to :client
attr_accessible :client_id
validates :client_id, presence: true
end
class Client < User
attr_accessible :appId, :expire_date, :legacy, :url, :plan_id, :chat_window_color, :chat_head_color, :chat_box_container_color, :chat_box_color, :tab_message, :greeting, :please_wait_message, :send_message_button, :comments_label, :offline_message
belongs_to :plan
has_many :agents, :dependent => :destroy
has_secure_password
after_initialize :init
#omited validations
private
#BEGIN PRIVATE METHODS
end
Both inherit from user
class User < ActiveRecord::Base
self.abstract_class = true
attr_accessible :email, :name, :password, :password_confirmation
attr_accessor :updating_password
has_secure_password
before_save { self.email.downcase! }
#the controller must set updating_password to FALSE to avoid validation
def should_update_password?
updating_password || new_record?
end
end
So I found the issue, the column client_id is a varchar and mysql allowed this but postgres complained about the different datatypes. Got a mgiration working by doing something like this:
def up
rename_column :agents, :client_id, :client_id_old
add_column :agents, :client_id, :integer
Agent.reset_column_information
Agent.find_each { |c| c.update_attribute(:client_id, c.client_id_old) }
remove_column :agents, :client_id_old
end
From this link How do I change column type in Heroku?.
To avoid the issues when changing datatypes in postgres directly with change_column. Hope this helps someone else
Let's say I'm starting out with this model:
class Location < ActiveRecord::Base
attr_accessible :company_name, :location_name
end
Now I want to refactor one of the values into an associated model.
class CreateCompanies < ActiveRecord::Migration
def self.up
create_table :companies do |t|
t.string :name, :null => false
t.timestamps
end
add_column :locations, :company_id, :integer, :null => false
end
def self.down
drop_table :companies
remove_column :locations, :company_id
end
end
class Location < ActiveRecord::Base
attr_accessible :location_name
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :locations
end
This all works fine during development, since I'm doing everything a step at a time; but if I try deploying this to my staging environment, I run into trouble.
The problem is that since my code has already changed to reflect the migration, it causes the environment to crash when it attempts to run the migration.
Has anyone else dealt with this problem? Am I resigned to splitting my deployment up into multiple steps?
UPDATE It appears I am mistaken; when migrating a coworker's environment we ran into trouble, but staging updated without issue. Mea Culpa. I'll mark #noodl's reply as the answer to bury this, his post is good advice anyway.
I think the solution here is to not write migrations which have any external dependencies. Your migrations should not depend on the past or current state of your model in order to execute.
That doesn't mean that you can't use your model objects, just that you shouldn't use the versions found in whatever version of your code happens to be installed when you run a particular migration.
Instead consider redefining your model objects within your migration file. In most cases I find that an empty model class extending ActiveRecord::Base or a very stripped down version of the model class I was using at the time I wrote the migration allows me to write a reliable, future proof, migration without needing to convert ruby logic into SQL.
#20110111193815_stop_writing_fragile_migrations.rb
class StopWritingFragileMigrations < ActiveRecord::Migration
class ModelInNeedOfMigrating < ActiveRecord::Base
def matches_business_rule?
#logic copied from model when I created the migration
end
end
def self.up
add_column :model_in_need_of_migrating, :fancy_flag, :boolean, :default => false
#do some transform which would be difficult for me to do in SQL
ModelInNeedOfMigrating.all.each do |model|
model.update_attributes! :fancy_flag => true if model.created_at.cwday == 1 && model.matches_business_rule?
#...
end
end
def self.down
#undo that transformation as necessary
#...
end
end
What error are you getting when you run the migrations? You should be fine as long as your rake files and migrations don't use your models (and they shouldn't).
You'll also want to switch the order of your drop_table and remove_column lines in the self.down of your migration.