rails object.association.count postgres error - ruby-on-rails

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

Related

Rails model foreign key validation

I need to validate the existence of a row referenced by a foreign key in one of my models. The situation is like this:
Project.rb
class Project < ActiveRecord::Base
has_one :project_category
# -----------------------------------------------------------------
# this does not work because the attribute is actually called
# 'category_id' instead of the rails expected 'project_category_id'
# -----------------------------------------------------------------
validates :project_category, presence: true
end
Project Migration
class CreateProjects < ActiveRecord::Migration
def change
create_table :projects do |t|
# ----------------------------------------------
# this is why the column is called 'category_id'
# ----------------------------------------------
t.references :category, references: :project_categories, null: false
# all of my other fields here, unimportant
end
add_foreign_key :projects, :project_categories, column: :category_id
end
end
I know that I can write a custom validation method to check if the :category_id exists in the project_categories table but I would prefer to let rails handle the validation if there is a way, so I can keep my code DRY.
EDIT
ProjectCategory.rb
class ProjectCategory < ActiveRecord::Base
belongs_to :project
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
ProjectCategory Migration
class CreateProjectCategories < ActiveRecord::Migration
def change
create_table :project_categories do |t|
t.string :name, null: false
end
end
end
It appears you only need to add the foreign_key option to your has_one declaration in order to specify the custom column name you've specified i.e. category_id instead of project_category_id. See Options for has_one for details.
# app/modeles/project.rb
class Project < ActiveRecord::Base
has_one :project_category, foreign_key: 'category_id'
# -----------------------------------------------------------------
# this does not work because the attribute is actually called
# 'category_id' instead of the rails expected 'project_category_id'
# -----------------------------------------------------------------
validates :project_category, presence: true
end

Why isn't this rails file attachment (using dragonfly) loading?

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.

Mongo + RoR Models. Stuck with NoMethodError

I have a problem with NoMethodError in one of my models.
In the log file, we have:
NoMethodError (undefined method `length=' for #<Book:0x000000083866b8>):
2013-03-28T10:25:19+00:00 app[web.1]: app/models/engine/book.rb:13:in `block in find_or_create_by_guide'
2013-03-28T10:25:19+00:00 app[web.1]: app/models/engine/book.rb:9:in `find_or_create_by_guide'
Let me go through all of the important files.
For a start, we have Mongo's document.rb:
class Guide::Document
include MongoMapper::Document
key :city, Integer
key :trips, Array
key :themes, Array
key :places, Array
key :pace, String
key :date_from, Time
key :date_to, Time
key :host, String
key :length, Integer
timestamps!
end
Then, the book model is called upon the guide document:
module ClassMethods
def find_or_create_by_guide(guide)
book = ::Book.find_or_create_by_document(guide.id.to_s) do |b|
b.city_id = guide.city
b.host = guide.host
b.pace = guide.pace || :normal
b.length = guide.length
end
later in the book.rb, I have the following line:
groups = sorted_points.in_groups_of(self.length.count, false)
Length.rb:
class Length < ActiveRecord::Base
belongs_to :book
attr_accessible :book_id
end
Book.rb:
attr_accessible :user_id, :country_id, :city_id, :hotel_id, :type, :price, :host, :pace, :created_at, :updated_at, :length
Finally, the migrations of Length:
class AddLengthColumnToBooks < ActiveRecord::Migration
def change
add_column :books, :length, :integer
end
end
Any hints or tips appreciated.
This is a mess. Once you want 'length' to be an attribute of Book, once you want Length to be a separate model which is in a relation with Book.
I see no point in having Length model.
Go with 'length' as a Book property.

Default values for model attributes in Rails

What's the proper way to set default values for models in Rails?
class User < ActiveRecord::Base
attr_accessible :name, :points
end
I want points to start out at 0 instead of nil. Ideally the default value is created right away rather than waiting for the User to be saved into the database. But I guess using a before_save or database constraints work as well:
class User < ActiveRecord::Base
attr_accessible :name, :points
before_save :set_defaults
private
def set_defaults
self.points = 0
end
end
Using the latest stable Rails.
set it in your migration:
t.integer :points, default: 0
You can set default value by migration or by using model setter methods.
change_column :user, :points, :integer, :default => 0
Or,
def points
#points ||= 0
end

Mechanize mass assignment error for HABTM join table

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

Resources