populate random data in ruby on rails - ruby-on-rails

I need help in populate some random data in my database table.
I have a list of 10 users in my system. My allergy table has the following fields:
id user_id name reactions status
I have the following allergies hash in a variable called allergy_hash.
{:reaction_name=>"Bleeding", :status=>"Death", :name=>"A"} {:reaction_name=>"Nausea", :status=>"Serious", :name=>"B"} {:reaction_name=>"Fever", :status=>"Death", :name=>"C"} {:reaction_name=>"Blistering", :status=>"Serious", :name=>"D"}
Here is what I have done so far:
def create_random_data
users.each do |user|
allergies.each do |allergies_hash|
Allergy.where(user_id: user.id).first_or_create(
allergies_hash )
end
end
end
What the above does is just inserts Bleeding, Death and A into the table for all users 1 to 10.
But I need to insert such that different users can have different values. Also some users can have more than one allergy and the associated reactions.
NOTE: I do not mean completely random. For example name 'A' should still have the associated status 'Death' and reaction_name 'Bleeding'.
Name 'B' should have the associated status 'Serious' and reaction 'Nausea'in the allergy table.

When creating the users, use sample on allergies_hash = [{:reaction_name=>"Bleeding", :status=>"Death", :name=>"A"}, {:reaction_name=>"Nausea", :status=>"Serious", :name=>"B"}, {:reaction_name=>"Fever", :status=>"Death", :name=>"C"}, {:reaction_name=>"Blistering", :status=>"Serious", :name=>"D"}]
Allergy.where(user_id: user.id).first_or_create(allergies_hash.sample)
UPDATE
I'll loop through the users instead, so for each user you attempt to add from 1 to 3 allergies from your allergies_hash
User.all.each do |user|
[1,2,3].sample.times do
user.allergies.where(allergies_hash.sample).first_or_create
end
end

I would recommend you to check Faker and Factory girl to populate some random data.

You can either seed data into your app by going to the seed file in the app/db directory
and do something like this
User.delete_all
Bill.delete_all
u1 = User.create(:email => "bob#aol.com", :password =>"a", :password_confirmation => "a")
b1 = Bill.create(:name => "rent", :description => "the rent", :amount => 10_000, :day => 1)
b2 = Bill.create(:name => "cable", :description => "the cable", :amount => 150, :day => 5)
or you can also use the Faker gem to generate fake data.
http://geekswithblogs.net/alexmoore/archive/2010/01/18/faker-gem---a-quick-and-dirty-introduction.aspx

Related

How does ORM relate classes/attributes to tables/fields?

I'm trying to understand ORM and looking for examples of the following explanation:
tables map to classes,
rows map to objects,
columns map to object attributes
I understand that tables map to classes, but terminology of rows mapping to objects and columns mapping to object attributes have me confused.
I find actual examples help best. Try this:
Ruby and Rails:
Create the class (Create the table)
class House < ActiveRecord::Base
attr :length, :width, :finish, :price, :available
end
Create an instance (Insert a row)
my_house = House.new(:length => 23, :width => 12, :finish => 'siding',
:price => '$100,000.00', :available => false)
Get an instance (Select a row)
my_house = House.find(1)
puts my_house.length, my_house.width, my_house.price,
my_house.finish, my_house.available?
SQL:
Create the table (Create the class)
create table house(
length Integer,
width Integer,
finish Varchar(255),
price Text,
available Boolean)
# Note this is generic SQL, adapt as needed
# to your implementation - SQLserver, Oracle, mySQL, etc.
Insert a row (Create an instance)
insert into house (length,width,finish,price,available)
values (23, 12, 'siding', '$100,000.00', false)
Select a row (Get an instance)
my_house = select * from house where id = 1
Here appeared some good answer while i was painting, but still hopes my simple one would help:
(since you've tagged your question with 'rails', I apply rails code)
class User < ActiveRecord::Base
attr_accessor :first_name, :email
end
puts User.inspect # => class
puts u = User.create(:first_name => 'name',
:email => 'em#il.com') # => object (class instance)
puts u.name # => object's attribute
DB:
So, using ActiveRecord as the example, let's say you have a table posts, with columns 'id', 'title', 'date'. There are 2 rows in the posts table.
posts = Post.all
posts will be an Array of length 2. Each object in the array is one of the rows, and is an instance of class Post.
posts[0]
This is the first object in the array, which is the representation of the first row in the posts table.
posts[0].title
This will return the title attribute of the first object, which is the title column in the first row of the posts table.
Does that help?

how to append database records in to a variable in ruby on rails

I fetched all users from the database based on city name.
Here is my code:
#othertask = User.find(:all, :conditions => { :city => params[:city]})
#othertask.each do |o|
#other_tasks = Micropost.where(:user_id => o.id).all
end
My problem is when loop gets completed, #other_task holds only last record value.
Is it possible to append all ids record in one variable?
You should be using a join for something like this, rather than looping and making N additional queries, one for each user. As you now have it, your code is first getting all users with a given city attribute value, then for each user you are again querying the DB to get a micropost (Micropost.where(:user_id => o.id)). That is extremely inefficient.
You are searching for all microposts which have a user whose city is params[:city], correct? Then there is no need to first find all users, instead query the microposts table directly:
#posts = Micropost.joins(:user).where('users.city' => params[:city])
This will find you all posts whose user has a city attribute which equals params[:city].
p.s. I would strongly recommend reading the Ruby on Rails guide on ActiveRecord associations for more details on how to use associations effectively.
you can do it by following way
#othertask = User.find(:all, :conditions => { :city => params[:city]})
#other_tasks = Array.new
#othertask.each do |o|
#other_tasks << Micropost.where(:user_id => o.id).all
end
Here is the updated code:
#othertask = User.find_all_by_city(params[:city])
#other_tasks = Array.new
#othertask.each do |o|
#other_tasks << Micropost.find_all_by_user_id(o.id)
end
You are only getting the last record because of using '=' operator, instead you need to use '<<' operator in ruby which will append the incoming records in to the array specified.
:)
Try:
User model:
has_many :microposts
Micropost model:
belongs_to :user
Query
#Microposts = Micropost.joins(:user).where('users.city' => params[:city])

rake db:seed populate keys when seed

I have state data in a txt file that I used to seed my States db which has columns :id and :name. the :name is the state 2-digit code. Used the following code in seeds.rb file:
State.delete_all
open("C:/Sites/rails_projects/sales_tracking/lib/assets/states.txt") do |states|
states.read.each_line do |state|
name = state
State.create!(:name => name)
end
end
I now have my Cities.txt file with data of city,state. My cities db has columns :id, :name, :state_id. :state_id is the foreign key from the states table. What code do I need to add to the below part of my seeds.rb file to populate the :state_id while running rake db:seed on the city seed data ("code" is 2-digit state id).
City.delete_all
open("C:/Sites/rails_projects/sales_tracking/lib/assets/cities.txt") do |cities|
cities.read.each_line do |city|
name, code = city.chomp.split(",")
??
City.create!(:name => name, :state_id => state_id)
end
end
Use a dynamic finder to get the state:
City.create!(:name => name, :state => State.find_by_name(code))
Or if you'd like to avoid a few queries, and if the state code is guaranteed to exist, you can keep track of the states as you seed them in a hash and reuse them for the cities:
State.delete_all
City.delete_all
#states = {}
open("states.txt").read.each_line do |code|
#states[code] = State.create!(:name => code)
end
open("cities.txt").read.each_line do |city|
name, code = city.chomp.split(",")
City.create!(:name => name, :state => #states[code])
end

How do I seed a belongs_to association?

I would like to seed my Products and assign them to a specific User and Store.
Product.rb
class Product < ActiveRecord::Base
belongs_to :user
belongs_to :store
def product_store=(id)
self.store_id = id
end
end
Note: Store belongs_to Business (:business_name)
Seed.rb
This is my basic setup:
user = User.create(:username => 'user', :email => 'user2#email.com')
store = Store.create(:business_name => 'store', :address => 'Japan')
I attempted these but they did not work:
# This gives random ID's ranging from 1 to 4425!?
user.products.create([{:name => "Apple", :product_store => Store.find_by_address('San Francisco, USA')}])
# This gives me undefined method 'walmart'.
user.store.products.create([ {:name => "Apple"} ])
Is there a way to set the ID's so I can associate my Products to a Store and User?
UPDATE -
I have tried the answers below and still came out unsuccessful. Does anyone know of another way to do this?
Although it sounds like you found a workaround, the solution may be of interested to others.
From your original seeds.rb
user = User.create(:username => 'user', :email => 'user2#email.com')
store = Store.create(:business_name => 'store', :address => 'Japan')
Create the store
Store.create({
user_id: user.id
store_id: store.id
}, without_protection: true)
In the original code snipped "user" and "store" variables are declared. The code assigns user_id / store_id (the model columns inferred by the belongs_to relationship in the Store model) to the id values that are present in the "user" and "store" variables.
"without_protection: true" turns off bulk assignment protection on the id fields. This is perfectly acceptable in a seeds file but should be used with extreme caution when dealing with user provided data.
Or alternatively create your stores.
Then extract the correct one
e.g.
store = Store.find_by_business_name('Test Store')
and then create it based on that
e.g.
store.products.create(:product_name => "Product Test", :price => '985.93')
This will then set the relationship id for you,
If I'm not mistaken, you're just trying to do this.
user = User.create(:username => 'usertwo', :email => 'user2#email.com')
walmart = Store.create(:business_name => 'Walmart', :address => 'San Francisco, USA')
user.products.create(:name => 'Apple', :store => walmart)
Anything else required here that I'm not seeing?
Try doing this
store_1 = Store.new(:business_name => 'Test Store',
:address => 'Test Address',
:phone_number => '555-555-555')
store_1.id = 1
store_1.save!
The trick is not to set the id within the hash as it is protected.
Scott
What I did was update the particular products to a certain user, see this question:
Can I update all of my products to a specific user when seeding?
You could just create a series of insert satements for this "seed migration", including the record Id for each user, store, product etc. You might have to update database sequences after this approach.
Another approach
Create the initial records in you Rails app, through the GUI / web.
Then use something like Yaml-db. So you can dump the data to a yaml file. You can now edit that file (if necessary) and use that same file to seed another instance of the db with "rake db:load"
Either way.... You know the Ids will not be shifting around on you when these objects are created in the new db instance.
I'm sure there are other ways to do this... Probably better ones, even.
Here is a link to a write-up I did a while back for using yaml_db to seed an oracle database
http://davidbharrison.com/database_seeding_oracle
Try this:
User.destroy_all
Product.destroy_all
user = User.create!([{:username => 'usertwo', :email =>'user2#email.com'},
{:username => 'userthree', :email => user3#email.com}])
user.each_with_index do |obj, index|
Product.create!([{ :product_name => 'product #{index}', :user_id => obj.id }])
end
The table would look like this:
Here's how I prefer to seed an association in rails 6
#teacher = Teacher.new(name: "John")
#student = #teacher.build_student(name: "Chris")
#teacher.save!
#student.save!

Rails 3 - is possible to make IFs in a database query

I have a profile card of user that have registration in my forum.
Person.update_all({:name => params[:person][:name],
:sex => params[:person][:sex],
:age => params[:person][:age],
:avatar => params[:person][:avatar].original_filename,
:city => params[:person][:city]},
{:id => params[:id]})
This is query for updating data in database. But here is a small problem - this will work only in a situation, if I the user send through form avatar (image). If not send avatar - that means the user already have uploaded avatar and the form send only name, sex, age and city. So in this case I'll get error in line :avatar => params[:person][:avatar].original_filename, -- and I would like to ask you for, if exist some elegant way, how to treat this moment.
I thought something like this:
if params[:person][:avatar]
avatar = ':avatar => params[:person][:avatar].original_filename,'
end
Person.update_all({:name => params[:person][:name],
:sex => params[:person][:sex],
:age => params[:person][:age],
avatar
:city => params[:person][:city]},
{:id => params[:id]})
But unfortunately, this doesn't work... How you're solving similar situation?
Thank you.
Well, it seems, like your params[:person] keys are similar to your model fields. So why don't you just pass params[:person] to update_all?
Alternatively, you could create a hash person, initialize it the way you want and then pass it to update_all
person = { :name => params[:person][:name] ,
...
if params[:person][:avatar]
person[:avatar] = params[:person][:avatar].original_filename
end
Person.update(params[:id], person)
I've changed update_all to update, because update_all is used to update all the records (that match the condition), while update find's the record by it's ID.
But again, it's a bad practice and you have to type a lot of unnecessary code.
One more thing. update_all makes a direct DB call, which doesn't involve validations, callbacks etc.
So, if you don't have some special reason for this, you'd better do something like this:
#person = Person.find params[:id]
#person.update_attributes params[:person]
I really think, you should check this book out
Updated once again :)
You see, such things belong to your models, not controllers. You could define a setter in the model:
def avatar=(value)
write_attribute(:avatar, value.original_filename)
end

Resources