How to set default data in a table in rails? - ruby-on-rails

I have a table that I'm going to store units of measurements in and the corresponding category. For example, "cups, volume" and "ounce, mass". I only have about 12 measurements I care about, and I want them to be in the database without manually entering them because anytime I want to deploy it or move the code somewhere, I want this to recreate.
So, I figure the best way to do this is to create a csv file with them, and then use rake db:seed. But I've never done this before so can someone guide me as to how to create this csv, and how to write the seeds.rb file to generate that? Is this the right way to do it?
SOLUTION:
#db/seeds.rb
require 'open-uri'
#Supply all the units of measurement to be used
Unit.delete_all
open("db/seeds/measurements.csv") do |measurements|
measurements.read.each_line do |measurement|
unit, uof = measurement.chomp.split(",")
Unit.create!(:name => unit, :unit_of => uof)
end
end

Just write the code you'd use to generate them manually and put it in the seeds.rb. You can use normal ruby in that file; so either just write plain create's or load a csv you store in, e.g. db/seeds/measurements.csv. To get the path to that file, use Rails.root.join("db/seeds/measurements.csv").
Example:
File.open(Rails.root.join("db/seeds/measurements.csv")) do |f|
# use f here
end

There's a file called seeds.rb in db directory.
You can add your default data in it and when you execute rake db:seed, that data will be populated in your database.
Here's an example of how you can add seeds to it.
product_types = ProductType.create([
{:name => 'clock',:organisation_id => 1}
])

Related

Creating devise users from a CSV file - Rails - PG

I have been given a CSV file that contains emails and passwords.
My task is to go through this CSV file and create users using the devise gem.
You will probably wonder why I hace been given peoples emails and passwords (I am as well), but I've been told not to worry about it.
My csv file looks like this:
Email,Password,Password_confirmation,,
email1#email.com ,password1,password1,,
email2#email.com ,password2,password2,,
email3#email.com ,password3,password3,,
I wrote the following code in my seeds.rb file:
require 'csv'
CSV.foreach("db/fixtures/users.csv", :col_sep => ",", :headers => true) do |row|
User.create(email: row['email'], password: row['password'], password_confirmation: row['password_confirmation'])
end
I run rails db:seed to create the users, but nothing happens, no error messaged either.
Any support would be welcomed.
First of all, it's a really bad idea to put that file with actual passwords under version control and to import it in seeds.rb. Would be much better to add a rake task for that purpose accepting csv file path as an argument and perform it once in a suitable environment.
About the code, the headers in CSV import are case sensitive, so it would work if you get the row value via row['Email'], row['Password'] etc.
Also, make sure that filling in those fields are enough to save the user, there may be some other required fields in your particular model.

From external Web page to HTML stored in db

I need to read the content of a website, and save HTML of a part of this page.
For example, let's say I want to get only the description of an athlete on this page : https://www.olympic.org/usain-bolt : the section.text-content element.
How can I do in Rails to store that HTML in my database, to be able to provide it later via an API?
Anyone have a clue about this?
You can get the description easily openning the url, parsing the html and accessing the element you pointed, like:
require 'nokogiri'
require 'open-uri'
url = 'https://www.olympic.org/usain-bolt'
doc = Nokogiri.HTML(open(url))
puts doc.css('section.text-content').text
As you already have the data then you need a model where to store, you can create a new one, just as example called Athlete, using the rails generate command and migrate, like
$ rails g model Athlete description:text
$ rails db:migrate
The description is a text data type attribute, which allow you to store large texts, as the description.
Then you need to insert it, or update it. You can create a new record, and then update it. In the rails console, just:
Athlete.create
This will create a new athlete without description, but necessary to get it by its id. After that you can create a task, in the lib/tasks folder, you can create a file with .rake extension and add your code, using the way to create a task, like:
require 'nokogiri'
require 'open-uri'
namespace :feed do
desc 'Gets the athlete description and insert it in database.'
task athlete_description: :environment do
url = 'https://www.olympic.org/usain-bolt'
doc = Nokogiri.HTML(open(url))
description = doc.css('section.text-content').text
Athlete.find(1).update description: description
end
end
You have the libraries, get the data, and update to the record using ActiveRecord, you can easily run:
rails feed:athlete_description
# or
rake feed:athlete_description
Nokogiri might be able to do what you need by way of CSS selectors.
If not, you can use Net:HTTP to get the page contents into a local variable, then you can use string manipulation to find the piece you want and store it. Unfortunately, I don't think there's any straightforward way to select that element specifically with this method.

How to implement a user creating a file via form and then downloading it in rails?

I am building an online translation platform. When a job is done being translated and saved, I want the user to be able to download the translated version as a text file. It is currently saved in a string in the model called "target_text".
I know in ruby I can use this method:
File.open("translation.txt", 'w') {|f| f.write("my translated string") }
I am assuming I could tack the location for the file to be saved in front of the "translation.txt", but I am not sure what folder within my app I should specify?
Furthermore I want this file to be attached to the "job" object in the same way that paperclip can attach files, the difference being it's initiated server side. How should I go about this?
I have googled all over looking for an answer to this, and I want to make sure I do it in the cleanest way possible. I would really appreciate even directions to a good place to look to understand this concept.
I don't quite understand the question, but I hope this could help...
Instead of using
File.open("translation.txt", 'w') {|f| f.write("my translated string") }
try using the following
Tempfile.open(['translation', '.txt'], Rails.root.join('tmp')) do |file|
# this will create a temp file in RAILS_ROOT/tmp/ folder
# you can replace the 'translation' text part to any auto generated text for example
# Tempfile.open([#user.id.to_s, '_translation.txt'] will create
# RAILS_ROOT/tmp/1_translation.1fe2ed.txt
# the 1fe2ed is generated by Tempfile to avoid conflicting
begin
file << "my translated string"
# this creates the file
# add all the processing you need here... cause the next ensure block
# will close and delete this temp file... so that the tmp dir doesn't get big.
# you can for example add the file to paperclip attachment
#user.translation = file
# assuming that user has paperclip attachment called translation
ensure
# close and delete file
file.close
file.unlink
end
end
also check the Tempfile docs... this is the practice i've been using... not sure if it's the best or not.. but it didn't create any issues so far
(even with paperclip s3 storage)

How to control RoR I18n texts stored in database?

I'm using the I18n Gem from Sven Fuchs in my Ruby on Rails 3.2 Application and while the gem works great I came across a situation, which I don't know the solution to:
I have a seed file, which contains the basic translation for my MVC's and is seeded, when I install my application on a new machine. The problem is that when one of these translations changes, I have to go to my seed file, edit it, delete in the database and reseed it. Which is problem not the best way to do this.
Furthermore, my application can create complete MVC's on the fly, which of course need translations as well. These translations get only stored in the database. But it would be nice to store them in a real file, keep them under version control and import or export them if I need to.
So, basically what I'm looking for, is an intelligent connection between the translations in my database and the ones in my files. So I can populate one from the other or vica verca and keep them in sync.
And also I looked at solutions like Globalize3 or localeapp, but they don't seem to fit.
Summarized, what I have is:
The I18n Gem from Sven Fuchs with a Backend I created myself
A Seed File which changes sometimes and has to be edited manually but seeds the basic translations
A database which contains translations that are created on the fly and are not under version control, nor stored in some file
What I want:
A sync between translations in my seed file and my database
A way to put my translations under version control
I'm sure I can't be the only one who needs this...
Thanks in regards!
Here is how I solved a problem closer to the question asked:
task :task_name => [:environment] do
file = "db/file_name.txt"
counter = 0
CSV.foreach(file, :headers => true, :col_sep => "^", :quote_char => "~") do |row|
identifier = row[0].to_i
model_name = ModelName.find_or_create_by_identifier(identifier)
I18n.locale = row[1]
model_name.name = row[3]
model_name.save!
end
end
Note that identifier needs to be a unique identifier that doesn't change and exists in the file and in the database. In this example, the columns are separated by "^" and quores are "~"
As #tigrish said in the comments, it is not a good idea to insert in the file and in the database, so it is important to restrict this.
These links may also help:
http://railscasts.com/episodes/396-importing-csv-and-excel
http://jasonseifer.com/2010/04/06/rake-tutorial
As the question is a little old, I hope it can help somebody else.

Is there any gem can dump the data from and to yml files?

I'm find such a gem a whole day, but not find a good one. I want to write one, but I'm not able to do it.
The data in my database may be English text, which will be dump to a yml file with plain text. And some are non-English text, which will be binary type.
And both of them may have such code:
<% xxx %>
When I use rake db:fixtures:load to load them into database, error may occur: method xxx not found.
I wan't to find a good gem can handle this problem. Thank for any help
UPDATE
I have gave up finding such a gem. At first, I think it's a easy task, but now, after some researchings, I have to say, it's much harder than I expected.
The reason you are having problems is because the Fixture loader will pass your fixture through erb before loading the data. This means that if you have <% xxx %> in your yaml file then Rails will see that as erb and try to run a method called xxx.
There does not seem to be an easy way to turn off erb processing of fixtures. I have tried replacing the fixtures with CSV fixtures and this still does ERB pre-processing.
Without a simple answer I have to ask the question Why do you have these strings in your file?
Do you want them to be expanded by erb?
Err...I'm not sure if you actually need a gem for this? Rails natively can turn any model into YAML.
Let's say you have a model called "Objects". You could hit a route that looks like:
/objects.yaml
and you would get a giant text file of all your Objects in YAML form.
Of course, you would want to have something like:
respond_to do |format|
format.yaml {render :yaml => #objects}
end
in your restful controller.
If you'd rather not hit a route to do this, you can always do
#yaml = []
#objects.each do |object|
#yaml.push object.to_yaml
end
anywhere in ruby, which will give you an array of yaml objects, that you can then write to a file at your leisure.
I imagine that if rails itself is generating the yaml, then it would be able to then later load it as a fixture?

Resources