How to save metadata into database from a rake file (rails)? - ruby-on-rails

I am building a script to scrape data from a website. You can see the full code here: Undefined method 'click' for nil:NilClass (Mechanize)
Anyways, I have trouble to save this metadata into the database:
members = member_links.map do |link|
member = link.click
name = member.search('title').text.split('|')[0]
institution = member.search('td~ td+ td').text.split(':')[0]
dob = member.search('.birthdate').text.strip[1..4]
{
name: name.strip,
institution: institution.strip,
dob: dob,
bio: bio
}
end
Thus, how can I accomplish this?

Well, it should be as simple as:
Datum.create!(
name: name.strip,
institution: institution.strip,
dob: dob,
bio: bio
)
This is very basic Rails knowledge, make sure you've read Active Record Basics guide.

Related

Rails. Create an object with its association in one transaction

I need to create an object with the associated item all in the step of creation.
Although I have tried creating first, and then second, this gives problems in the way that if the second fails, then I get with the first part half done.
Relationship one user has many companies
I mean something like
user = User.create!(
email: prospect.email,
first_name: prospect.first_name,
last_name: prospect.last_name,
#birthdate:prospect.user_birthday,
id_number: prospect.id_number,
phone: prospect.phone,
address: prospect.address,
password: prospect.id_number,
password_confirmation: prospect.id_number,
company = user.companies.create(
name: prospect.vat_company_name,
plan: prospect.plan,
address: prospect.address,
description: prospect.company_description,
email: prospect.email,
phone: prospect.phone,
network_id: prospect.network_id
)
current_company_id: company.id
)
which of course fails because maybe it can't be done directly.
I have tried build instead of create, but same result.
I also know that second create will fail because the first object doesn't exist yet.
How is the best way?
You can create them both separately and wrap them in a transaction:
ActiveRecord::Base.transaction do
user = User.create!(...)
company = Company.create!(...)
end
This way if one of them fails, the other doesn't end up being committed to the database.
If you are talking about separate instance storage then using a db transaction lock is the way to go forward as mentioned by Danial. But if you only need to create an associated record of active record then you can do with Active Record only. It would make sure that both records are saved.
user = User.new
email: prospect.email,
first_name: prospect.first_name,
last_name: prospect.last_name,
#birthdate:prospect.user_birthday,
id_number: prospect.id_number,
phone: prospect.phone,
address: prospect.address,
password: prospect.id_number,
password_confirmation: prospect.id_number
user.build_current_company
name: prospect.vat_company_name,
plan: prospect.plan,
address: prospect.address,
description: prospect.company_description,
email: prospect.email,
phone: prospect.phone,
network_id: prospect.network_id
user.save!
This will create both user and it's current company.
(I am taking an assumption that you have belongs_to :current_company,class_name: 'Company' in user.rb)

Subnodes in a json template

I have a template for json using the JB gem: index.json.jb
https://github.com/amatsuda/jb
It outputs all the settings with some attributes per record.
Settings also have a metadata field, which is a postgres jsonB field. I'd like to loop through the metadata fields contents and add it to my json template. I've tried all sorts of ways and I can't figure out how to do this.
json = {}
json[:settings] = #settings.map do |setting|
{
id: setting.id,
category: setting.category,
created_at: setting.created_at,
updated_at: setting.updated_at,
notes: setting.notes,
name: setting.full_name,
setting.metadata.map do |meta|
{
meta[0]: meta[1]
}
end
}
end

Gem Koala Facebook API get_object request

I'm trying to get user's info via Gem Koala Facebook API with below code
#graph = Koala::Facebook::API.new(auth_hash.credentials.token)
profile = #graph.get_object("me")
user.update(
url: auth_hash.extra.raw_info.id,
email: auth_hash.extra.raw_info.email,
friends: #graph.get_connections("me", "friends"),
birthday: #graph.get_object("me", "birthday")
)
friends: #graph.get_connections("me", "friends") works perfectly fine, I will get a list of friends.
However birthday: #graph.get_object("me", "birthday") will give me type: OAuthException, code: 2500, message: Unknown path components: /birthday [HTTP 400]
Things that returns arrays such as likes, photos works fine.
But strings such as last_name, name, first_name will give me the same error.
What can I do to fix this? Is there something else I can enter instead of just birthday
Although it is not very well documented, I read the code of the gem.
Here it explains how to do what you want.
You can do it like this:
Koala::Facebook::API.new(ACCESS_TOKEN).get_object(:me, { fields: [:birthday]})
This will return the birthday and the id of the user.
birthday is not an endpoint like friends, it´s just a field in the user table. Same for name, first_name and last_name:
/me?fields=name,birthday,first_name,last_name
I have no clue about Ruby and Koala, but i assume you can add the fields parameter as object - this is what it looks like in the docs:
#graph.get_object("me", {}, api_version: "v2.0")
Source: https://github.com/arsduo/koala
I think this should do it!
rest = Koala::Facebook::API.new(access_token)
rest.get_object("me?fields=birthday")

Rails: Use a variable as a hash key

I've been trying to do this for the past 10 hours, but it's been useless.
For example:
Event.where(login_screen: Time.now-8.days ..Time.now)
I have an Event table and login_screen is one of the column names. I'm listing them in a drop-down menu and I'd like to take the event names as a variable. It's in the request params like this: params[:segmentation][:first_event]. When I tried to give it like:
Event.where(params[:segmentation][:first_event] Time.now-8.days ..Time.now)
...it didn't work. I tried to use to_sym but that didn't help either.
How can I use a variable as a symbol?
Another question:
What's the difference between :hello and hello: ?
It's alternative syntax for ruby hashes with symbols as keys
Event.where(login_screen: Time.now-8.days ..Time.now)
is the same as
Event.where(:login_screen => Time.now-8.days ..Time.now)
So, if you store key in variable you need use 'hash rocket' syntax:
Event.where(params[:segmentation][:first_event] => Time.now-8.days ..Time.now)
these are the different ways to pass arguments in where clause:--
User.where(["name = ? and email = ?", "Joe", "joe#example.com"])
User.where(["name = :name and email = :email", { name: "Joe", email: "joe#example.com" }])
User.where("name = :name and email = :email", { name: "Joe", email: "joe#example.com" })
using hash:-
User.where({ created_at: (Time.now.midnight - 1.day)..Time.now.midnight })
User.where({ name: ["Alice", "Bob"]})
User.where({ name: "Joe", email: "joe#example.com" })

Mongoid: Creating many objects with a single call

I have 1000 users that i will be retrieving from Twitter, and I would like to save them at one shot, as opposed to doing 1000 insertions individually.
How can I do this on Mongoid? Something like this would rock:
TwitterUser.createMany([{:name=>u1}, {:name=>u2},{:name=>u3}] )
You should use the Mongo ruby driver to do this. You can pass an array of hashes to the insert method to create multiple documents at once (more info on this google groups discussion). Mongoid makes it easy to access the ruby driver.
The code would look something like this:
user_list = twitter_accounts.map do |account|
# create a hash of all the fields to be stored in each document
{ 'name' => account.name,
'username' => account.username
# some other fields...
}
end
Mongoid.master['twitter_users'].insert(user_list)
You almost got it, it's create, not createMany. You can use it like this:
TwitterUser.create([
{ username: "u1", display_name: "Display Name 1" },
{ username: "u2", display_name: "Display Name 2" },
{ username: "u3", display_name: "Display Name 3" }
])
Also, as #bowsersenior points out, it's a good idea to use it with Array#Map:
TwitterUser.create(
#users_array.map do |u|
{ username: u.username, display_name: u.name }
end
)
From the Mongoid#Persistence Docs:
Model.create
Insert a document or multiple documents into the database
Model.create!
Insert a document or multiple documents into the database, raising an error if a validation error occurs.
Just use MongoidModel.create directly.

Resources