Rails 4 Script + Error: Migrating Data From One Table to Another - mysql

I have created a script that I want to use to populate a new table in another database, as I'm moving this table out of one DB(table_1) and into another DB(db_2). I've already created the 'new_geo_fence' table in the new DB (db_2) and want to have the script run below to migrate data over. Script below:
class NewGeoFence < ActiveRecord::Base
attr_accessible :name, :address, :latitude, :longitude, :radius, :customer_id
belongs_to :customer, :foreign_key => 'customer_id'
end
require 'rubygems'
GeoFence.all.each do |g|
gf = NewGeoFence.new(
:id => g.id,
:name => g.name,
:address => g.address,
:latitude => g.latitude,
:longitude => g.longitude,
:radius => g.radius,
:created_at => g.created_at,
:updated_at => g.updated_at,
:customer_id => g.customer_id
)
gf.save
end
However, when I run it, I get this error:
/activerecord-4.0.13/lib/active_record/attribute_assignment.rb:47:in `rescue in _assign_attribute': unknown attribute: customer_id (ActiveRecord::UnknownAttributeError)
What have I missed to get this script running?
Thanks!

You're calling each on a class when you should be calling it on an array of objects, so
GeoFence.all.each do |g|

Rails 4 requires parameters to be whitelisted when doing mass assignment. To do so, use strong parameters
GeoFence.all.each do |g|
params = ActionController::Parameters.new({
geofence: {
id: g.id,
name: g.name,
address: g.address,
latitude: g.latitude,
longitude: g.longitude,
radius: g.radius,
created_at: g.created_at,
updated_at: g.updated_at,
customer_id: g.customer_id
}
})
gf = NewGeoFence.new(params.require(:geofence).permit!)
gf.save
end

Related

Adding current location to Ruby on Rails app with photo_geoloader

So I've sent about 3 days researching geoip, geocoder, cookies, sessions, html5 and so forth.
I am trying to add a current location (as of the location when the user posts the photo in form). The user will not change this data, I just want it to be automatically added to the post, and then added to the view of the post (currently i am using .time_ago for the timestamp of the post). I can currently show in a map, but am lost as to adding it to the post.
I prefer to user HTML5 or
rails #lat_lng = cookies[:lat_lng].split("|").
I just need it printed to the post of each user.
I have tried using Exifr gem to extract that data but it is not precise enough. I am interested also in photo_geoloader gem yet there is little documentation.
So far i have created a model using "photo" as my model name. Currently I am validating the uploaded image through my "post" model;
class Post < ActiveRecord::Base
acts_as_votable
belongs_to :model
has_many :comments, dependent: :destroy
has_many :notifications, dependent: :destroy
validates :model_id, presence: true
validates :image, presence: true
validates :caption, length: { minimum: 3, maximum: 300 }
has_attached_file :image,
styles: lambda { |a| a.instance.check_image_type}
def check_image_type
if is_image_type?
{:medium => "640"}
elsif is_video_type?
{
:medium => { :geometry => "640x480", :format => 'flv'},
:thumb => { :geometry => "100x100#", :format => 'jpg', :time => 10}, :processors => [:transcoder]
}
else
{}
end
end
def is_image_type?
image_content_type =~ %r(image)
end
def is_video_type?
image_content_type =~ %r(video)
end
validates_attachment_content_type :image, :content_type => [/\Aimage\/.*\Z/, /\Avideo\/.*\Z/, /\Aaudio\/.*\Z/]
scope :of_followed_models, -> (following_models) { where model_id: following_models }
end
I have researched everything so I'm looking for a full process in rails 5 :)

Trouble defining finder method in my application

I’m using Rails 4.2.3 and MySQL 5.5.37. I want to write a finder method for my model, so I have written this (./app/models/user_object.rb):
class UserObject < ActiveRecord::Base
validates :day, :presence => true
validates_numericality_of :total
validates :object, :presence => true
def find_total_by_user_object_and_year
UserObject.sum(:total, :conditions => ['user_id = ?', params[:user_id], 'object = ?', params[:object], 'year(day) = ?', params[:year]])
end
end
However, when I attempt to invoke the method within a controller like so
#my_total = UserObject.find_total_by_user_object_and_year(session["user_id"], 3, #year)
I get the following error
undefined method `find_total_by_user_object_and_year' for #<Class:0x007fb7551514e0>
What is the right way to define my finder method?
Use self.method to define class method:
def self.find_total_by_user_object_and_year
sum(:total, :conditions => ['user_id = ?', params[:user_id], 'object = ?', params[:object], 'year(day) = ?', params[:year]])
end
In this case UserObject inside class method definition is redundant, besause it is same as self. Now you can write:
UserObject.find_total_by_user_object_and_year(params)

Rails search a model based on multiple parameters using a form

So... I've been working on creating a search form for a rails application. I've gone through the railscast episodes 37, 111, and 112.
While the simple text search with a text input field works. I need to be able to define more parameters to refine the search.
I've found a few other methods, some using scopes...I keep running into issues getting any of these working in my application....
What I have right now is a simple form defined on my home index that points at my assets index:
<% form_tag assets_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select(:type_id, :type_id, Type.where("type_for = 'asset'"), :id, :name) %>
<%= submit_tag "Search", :search => nil %>
<% end %>
my asset.rb model:
class Asset < ActiveRecord::Base
has_many :children_assets, :class_name => "Asset"
has_and_belongs_to_many :groups, :join_table => "assets_groups"
belongs_to :parent_asset,
:class_name => "Asset",
:foreign_key => "parent_asset_id"
belongs_to :asset_type,
:class_name => "Type",
:conditions => "type_for = 'asset'"
belongs_to :asset_status,
:class_name => "Status",
:conditions => "status_for = 'asset'"
belongs_to :location
belongs_to :funding_source
has_many :transactions
def self.search(search)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{search}"])
else
find(:all)
end
end
end
in the asset_controller.rb
def index
unless params[:search].nil?
#title = "Assets"
#search = params[:search]
#assets = Asset.search(params[:search]).paginate(page: params[:page], per_page: 25)
else
#title = "Assets"
#assets = Asset.where('').paginate(page: params[:page], per_page: 25)
end
end
I just dont understand what it is that I'm not seeing here. I can run a similar mysql query and get the result I want. I just dont know how to format this in rails...
Any guidance on this would be amazing right now. Thanks!
It looks as though you're trying to search for a specific type of asset, but your search method in the Asset model is only using one of the user supplied parameters.
Judging by the form you're using, your controller will be receiving the params
params = {
search: 'Search Text',
type_id: 1
}
In your controller, you're only using search, so I'd change your method to include this:
#assets = Asset.search(params[:search], params[:type_id]).paginate(page: params[:page], per_page: 25)
Then amend the Assets model to use it
def self.search(search, type_id)
if search
find(:all, :conditions => ['nmc_name LIKE ? AND type_id = ?', "%#{search}%", "%#{type_id}"])
else
find(:all)
end
end

".save" only inserts null values in database

I'm trying to make a RoR application for a Hospital so it has patients, doctors, offices, etc.
The problem I'm having is that, at the patient "Sign-up", I'm not able to save the new patient in the database. In fact, despite I've checked that the attributes are ok (It's just a name and a personal ID), once the method is excecuted, in the database only appears a new row with "<null>" instead of the actual attribute values. Here's the method:
def pat_create
pName = params[:name].to_s
id = params[:pid].to_s.to_i
pat = Patient.where(:pID => id).first
if pat == nil
pat = Patient.new(:name => pName, :pID =>id)
pat.save
end
end
Also, This is the query that it constructs:
INSERT INTO `patients` (`created_at`, `name`, `pID`, `updated_at`) VALUES ('2013-05-20 02:04:28', NULL, NULL, '2013-05-20 02:04:28')
This method is called after some other view collects the :name and :pid information in this form:
<%= form_tag('/page/pat_create') do %>
<%= text_field_tag :name, nil%>
<%= text_field_tag :pid, nil%>
<%= button_tag(type: "submit", class: "btn btn-success") do %>
Register<i class="icon-white icon-plus"></i>
<%end%>
<%end%>
Needless to say, pat.errors.empty? is true, and so is pat.save.
Any idea why this happens?
Here's Patient Model:
class Patient < ActiveRecord::Base
attr_accessible :name, :pID
attr_accessor :name, :pID
has_many :appointments
validates_presence_of :name
validates :name, :format => {:with=> /^[a-zA-Z\s\D]+$/}
validates_presence_of :pID
validates_numericality_of :pID
validates_inclusion_of :pID, :in => 100000..9999999999
end
Remove the following line in class Patient:
attr_accessor :name, :pID
What happened was that attr_accessor replaced the two database column attributes :name and :pID (which were automatically generated) with its own, resulting in two virtual attributes, :name and :pID.
Thus, the virtual attributes were being set and validated instead of the corresponding database attributes, which resulted in no errors yet null values in the database.
Can you show us how this method is called? Also are you sure that params[:name] and params[:pid].
You have used the column :pid and :pID, as below
pat = Patient.where(:pID => id).first
if pat == nil
pat = Patient.new(:name => pName, :pID =>id) # should use pat = Patient.new(:name => pName, :pid =>id)
pat.save
end
So in your controller your params are nil but you call .to_s and .to_s.to_i which results in an empty string "" and 0 (zero). You then save them into your database. A couple recommendations:
def pat_create
pat = Patient.new(:name => params[:name], :pid =>params[:pid])
pat.save
end
In addition to the uniqueness validation I would make sure your db column has a unique index on it to insure no duplicate patients.
class Patient < ActiveRecord::Base
attr_accessible :name, :pid
attr_accessor :name, :pid
has_many :appointments
validates :name, presence: true,
length: { maximum: 50 },
format: {:with=> /^[a-zA-Z\s\D]+$/}
validates :pid, presence: true,
numericality: { only_integer: true,
greater_than_or_equal_to: 100000,
less_than_or_equal_to: 9999999999 },
uniqueness: true
end
If you are getting valid values this will work and if not you will see why it is not.

Tricky MySQL Query for messaging system in Rails - Please Help

I'm writing a facebook style messaging system for a Rails App and I'm having trouble selecting the Messages for the inbox (with will_paginate).
The messages are organized in threads, in the inbox the most recent message of a thread will appear with a link to it's thread. The thread is organized via a parent_id 1-n relationship with itself.
So far I'm using something like this:
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => 'User', :foreign_key => "sender_id"
belongs_to :recipient, :class_name => 'User', :foreign_key => "recipient_id"
has_many :children, :class_name => "Message", :foreign_key => "parent_id"
belongs_to :thread, :class_name => "Message", :foreign_key => "parent_id"
end
class MessagesController < ApplicationController
def inbox
#messages = current_user.received_messages.paginate :page => params[:page], :per_page => 10, :order => "created_at DESC"
end
end
That gives me all the messages, but for one thread the thread itself and the most recent message will appear (and not only the most recent message). I can also not use the GROUP BY clause, because for the thread itself (the parent so to say) the parent_id = nil of course.
Anyone got an idea on how to solve this in an elegant way? I already thought about adding the parent_id to the parent itself and then group by parent_id, but I'm not sure if that works.
Thanks
My solution would be to get a list of threads (which I'm assuming could be obtained by messages with no parent id). Then on the Message model, add a method that will find the latest message in the thread and return it. You can then use that method to obtain the latest method in each thread and put in a link to the head of the thread easily.
(Pseudo-)code:
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => 'User', :foreign_key => "sender_id"
belongs_to :recipient, :class_name => 'User', :foreign_key => "recipient_id"
has_many :children, :class_name => "Message", :foreign_key => "parent_id"
belongs_to :thread, :class_name => "Message", :foreign_key => "parent_id"
def get_last_message_in_thread()
last_message = self
children.each do |c|
message = c.get_last_message_in_thread()
last_message = message if message.created_at > last_message.created_at
end
return last_message
end
end
class MessagesController < ApplicationController
def inbox
#messages = current_user.received_messages.find_by_parent_id(Null).paginate :page => params[:page], :per_page => 10, :order => "created_at DESC"
end
end
You could probably do a lot better than having a recursive function to find the last message in the thread, but it's the simplest solution I can think of to demonstrate the idea. I'm also not sure I have the correct syntax for finding unset parent id's in the inbox function, which is why I marked the code as pseudo code :)
giving the parent itself as parent makes it very easy to create queries that operate on the whole thread, because you can group (or anything similar) by parent_id.
if you handle the parents differently, all your queries have to take care of this too
The only efficient way would be to have a Thread model and use GROUP BY as you mentioned - Anything else would require iteration over the messages.
read update in comments
I figured the only good solution is using a second model to store the most recent messages for every thread (because of performance issues when using GROUP BY with a subselect, see my comments). It won't take a lot of space in the DB because we're only storing id's and no text or even blobs.
The RecentMessages Model would look something like this:
create_table :recent_messages do |t|
t.integer :sender_id
t.integer :recipient_id
t.integer :message_id
t.integer :message_thread_id
t.timestamps
end
class RecentMessage < ActiveRecord::Base
belongs_to :message
belongs_to :message_thread, :class_name => 'Message'
belongs_to :sender, :class_name => 'User', :foreign_key => "sender_id"
belongs_to :recipient, :class_name => 'User', :foreign_key => "recipient_id"
end
The main idea is: All the messages are stored in one model (Messages). Whenever a new message is added to a thread (or a thread is created), two things happen (e.g. with a after_save callback):
Store the new message in the RecentMessages model (that means sender_id, recipient_id, message_id, message_thread_id (= parent_id || id))
Get the most recent message (from this thread in messages), where sender_id == recipient_id and vice versa (note: This only works if the message model should only support messages between 2 users) and store it in the RecentMessages model as well (if found and if it's not already there)
Of course there should only be max. 2 recent_messages stored in the DB for every message_thread at any given time.
If one wants to show i.e. the inbox, the following has to happen:
#messages = current_user.recent_received_messages.paginate :page => params[:page], :per_page => 10, :order => "created_at DESC", :include => :message
That's the best I figured out so far. I still think it's ugly but it's fast and it works. If anyone comes up with a better solution, I'll be gratefull!
I don't know how to accomplish this in Rails, but this is how I did it directly in MySQL:
select * from messages where message_id in (
select max(message_id) from messages where to_uid = 51 group by thread_id
) order by timestamp desc
I used a subquery to grab the most recent message in a thread and then the main query to grab all of the fields for the messages found in the subquery.