I am using Devise for authentication, so I've aliased a few columns in my legacy database to accommodate it as follows:
class User < ActiveRecord::Base
set_table_name 'my_legacy_user_table'
set_primary_key 'UserId'
alias_attribute :id, :UserId
alias_attribute :username, :LoginId
alias_attribute :encrypted_password, :PasswordSHA1Hash
alias_attribute :first_name, :Name
alias_attribute :last_name, :Surname
devise :database_authenticatable, :authentication_keys => [:username]
attr_accessible :username, :password, :password_confirmation
def password_salt=(password_salt)
end
def password_salt
end
def password_digest(password)
self.class.encryptor_class.digest(password)
end
end
When I post to my /users/sign_in form, I get the following exception:
Mysql2::Error: Unknown column 'my_legacy_user_table.username' in 'where clause': SELECT `kms_User`.* FROM `my_legacy_user_table` WHERE (`my_legacy_user_table`.`username` = 'mrichman') LIMIT 1
I suppose I was under the assumption that alias_attribute would instruct ActiveRecord to use the real column name (UserId) and not the alias (username). What am I doing wrong?
Arel (the one that makes the SQL queries) still is not aware of ActiveRecord's aliases (up to 3.0.3). You should make sure that the query is made using the original name, LoginId, in this case.
If you enter the console and make a User.where(:username => "root") you see that it generates an error, although User.username works well.
For now just replace the username occurrences on sinup form until the upstream starts to support it.
EDIT: By the way, the recommended way of doing that is make a view! Don't forget that!
http://www.slideshare.net/napcs/rails-and-legacy-databases-railsconf-2009
Related
I am trying to go table-less with activerecord-tableless. The main reason to use it is for the associations. Here(in the github documentation) it tells you how to simply work with one model but doesn't say anything about associations.
For example: I have a User and Category model. Each User belongs to a Category.
This is my User model
class User < ActiveRecord::Base
has_no_table
belongs_to :category
column :id, :integer
column :name, :string
column :email, :string
column :password, :string
column :created_at, :string
column :updated_at, :string
column :category_id, :integer
validates :name, :email, :password, presence: true
validates_length_of :password, minimum: 8
end
Now, in the form, I have to get all the categories to select from like this
<%= f.collection_select(:category_id, Category.all, :id, :title) %>
From where, Category.all can retrieve its content. Do I have to override it?
Also, suppose I have a User object and I need to find it's Category object(if I have a category id), then will 'find' work?
If everything has to be overridden, then what is the use of activerecord-tableless.
I am not able to find any documentation or tutorials regarding this. Please help.
PS: I have tried ActiveModel as well but they do not support associations.
PPS: Rails 4.1.1 and Ruby 1.9.3 is being used.
I'm using active admin with ActiveRecord scopes. However, I'm having an issue with adding the scopes.
Running ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux] and
Rails 4.2.5.1
#app/model/accounts.rb
class Account < ActiveRecord::Base
searchkick
belongs_to :program
belongs_to :insurance
has_many :notes
scope :program_name, -> (program) {where(program_name: adult) }
validates :first_name, :last_name, :address, :phone, presence: true
validates :phone, format: { with: /\A\d{3} \d{3}-\d{4}\z/,
message: "must be in the format 123 456-7890" }
end
I want to be able to us this in app/admin/account.rb
#app/admin/account.rb
ActiveAdmin.register Account do
menu :priority => 2
permit_params :first_name, :last_name, :return_client, :program_id, :insurance_id, :address, :phone
index do
column :first_name
column :last_name
column :address
column :phone
column :created_at
column :return_client
column :program
column :insurance
actions
end
scope :all, :default => true
scope :adult, default: true do |accounts|
accounts.program_name('adult')
end
end
I tired using it with and without block. I want the total count of "programs" in that scope as an end result.
You can't have two default scopes and the scope :all is unnecessary so remove it.
You have this scope which looks fine
scope :program_name, -> (program) {where(program_name: adult) }
and you say that
I want to be able to us this in app/admin/account.rb
but you aren't actually using it. You are instead trying to use
scope :adult, default: true do |accounts|
accounts.program_name('adult')
end
So just add it
scope :program_name
But your question seems to be loaded with something else you're trying to do
I want the total count of "programs" in that scope as an end result.
And in that ^ sense, I think you may be misunderstanding how and what scopes are actually used for.
In spree Provided default registration form i was trying to add my few fields :contact_no, :address, :full_name.
Copied the complete view part from "spree_auth_devise" as Spree internally uses this Gem.
Added required form fields in app/views/spree/shared/_user_form.html.erb
Added required Migration
class AddUserRegistrationDetailsToSpreeUser < ActiveRecord::Migration
def change
add_column :spree_users, :full_name, :string
add_column :spree_users, :address, :text
add_column :spree_users, :contact_no, :integer
end
end
Now following Model part :
user_registration_decorator.rb
Spree::User.class_eval do
attr_accessible :email, :password, :password_confirmation,
:contact_no, :address,:full_name, :as => [:default, :user]
end
Now on creating a new user via registration form, in Database the newly added fields(contact_no, address, full_name) are saved with NULL Value. :(
Spree 2.1.3 runs on Rails 4, and has followed Rails 4 to make the switch to strong_parameters. You can read more about it in this blog post on the Rails Blog, but basically attr_accessible is no longer used, and has been replaced with explicitly allowed parameters in the controller.
You should take a look at modifying these attributes which are used by the user registrations controller.
I would like to use a model in Rails but not store it in DB. For example let's say I have a RSS reader. I would download some RSS data from other site and then create objects with specific model and show them to use. I don't want to store those objects in databse though. How can I do it?
I think your problem might easily be solved by just creating a class, alternatively you can use ActiveModel, it allows for the same behaviour without storing it in the db.
class RssReader
#include any behaviour you like
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
end
There is a very nice railscast on this at:
http://railscasts.com/episodes/219-active-model
You can also check this out(Rails 4)
http://blog.remarkablelabs.com/2012/12/activemodel-model-rails-4-countdown-to-2013
You're looking for tableless models, there are plenty of questions on SO about this:
Rails model without database
Rails Model without a table
and a handy railscast!
http://railscasts.com/episodes/193-tableless-model
In rails 2.3 You can do this by this way:
class OrderSession < ActiveRecord::Base
def self.columns() #columns ||= []; end
column :orderable_id, :integer
column :orderable_type, :string
column :subscription, :boolean
column :interval, :integer
column :quantity, :float
column :number, :integer
column :only_with_main_cart, :boolean
column :start_on, :date
attr_accessor :choice_item
attr_accessor :interval_choice_item_1
attr_accessor :interval_choice_item_2
validates_presence_of :orderable_id
validates_presence_of :orderable_type
validates_presence_of :interval
validates_numericality_of :quantity, :greater_than => 0
validates_inclusion_of :subscription, :in => [true, false]
validates_inclusion_of :only_with_main_cart, :in => [true, false]
end
I am using this for storing cart information before user confirmation
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