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)
Related
In my application I have Posts that Users can create. When I initially started my project, I created some placeholder Posts and Users from the command line just so I can play around. As the application advanced I created a seed file and ran 'rake db:seed' from the command line. Everything worked fine but I realized that I still had the placeholder Posts and Users still in the database so I decided to delete them. I decided to destroy all Posts and Users from the command line using the 'destroy_all' method. I just wanted to see if it would work and it did as everything was deleted. But now when I run 'rake db:seed' to populate the database, nothing shows up. I get no errors and nothing gets returned when I run Post.all or User.all from the command line. I'm not sure what's going on but I would appreciate any assistance, thank you!
User.create(name: 'John', email: 'John#gmail.com', password: '123456', password_confirmation: '123456')
User.create(name: 'Bill', email: 'Bill#gmail.com', password: '123456', password_confirmation: '123456')
Post.create([
{
user_id: 1,
category_id: 1,
title: "Tech tattoos put a working circuit board on your skin",
url: "http://www.slashgear.com/tech-tattoos-put-a-working-circuit-board-on-your-skin-25416060/"
},
{
user_id: 2,
category_id: 1,
title: "This robot can print emoji on your fingernails",
url: "http://mashable.com/2015/11/24/nailbot-printed-manicure/#Rml2qXalMmqp"
},
{
user_id: 3,
category_id: 2,
title: "Thiago Silva scores a goal from behind the goal",
url: "http://www.gyfbin.com/2015/11/hgfp.gif.html"
}])
Have a simple way to you can see error message at. You can use bang (!) after create method (ex: User.create!(.....), Post.create!(.....)). Console will raise error message when have any errors.
If you do same that. you can search yourself error.
destroy_all doesn't drop the table. First you ran the seed file. so, 5 users were created with ID (1 to 5). It destroys the USERS but not truncate. Then you destroy those users. Again ran the seed file. Now the 5 users were created with ID (6 to 10). So, there is no user_id with 1 anymore. It may be the problem.
solution 1: You can drop the tables (user, post) and then migrate and seed.
solution 2:
pick user ids randomly. Use:
users = User.all.collect{|u| u.id}
# same goes for category.
Post.create([
{
user_id: users.sample,
category_id: 1,
title: "Tech tattoos put a working circuit board on your skin",
url: "http://www.slashgear.com/tech-tattoos-put-a-working-circuit-board-on-your-skin-25416060/"
},
{
user_id: users.sample,
category_id: 1,
title: "This robot can print emoji on your fingernails",
url: "http://mashable.com/2015/11/24/nailbot-printed-manicure/#Rml2qXalMmqp"
},
{
user_id: users.sample,
category_id: 2,
title: "Thiago Silva scores a goal from behind the goal",
url: "http://www.gyfbin.com/2015/11/hgfp.gif.html"
}])
Hope it helps!
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.
I'm struggling to understand the relationship that owner = create(:user, device_token: device_token) has to owner: {device_token: device_token}, I usually use user_id for this association.
2. What is the device_token method in the controller is doing.
describe 'POST /v1/events' do
it 'saves the address, lat, lon, name, and started_at date' do
date = Time.zone.now
device_token = '123abcd456xyz'
owner = create(:user, device_token: device_token)
post '/v1/events', {
address: '123 Example St.',
ended_at: date,
lat: 1.0,
lon: 1.0,
name: 'Fun Place!!',
started_at: date,
owner: {
device_token: device_token
}
}.to_json, { 'Content-Type' => 'application/json' }
event = Event.last
expect(response_json).to eq({ 'id' => event.id })
expect(event.address).to eq '123 Example St.'
expect(event.ended_at.to_i).to eq date.to_i
expect(event.lat).to eq 1.0
expect(event.lon).to eq 1.0
expect(event.name).to eq 'Fun Place!!'
expect(event.started_at.to_i).to eq date.to_i
expect(event.owner).to eq owner
end
end
Controller Code:
def create
#event = Event.new(event_params)
if #event.save
render
end
end
private
def event_params
{
address: params[:address],
ended_at: params[:ended_at],
lat: params[:lat],
lon: params[:lon],
name: params[:name],
started_at: params[:started_at],
owner: user
}
end
def user
User.find_or_create_by(device_token: device_token)
end
def device_token
params[:owner].try(:[], :device_token)
end
end
There's a number of ways you can identify uniquely identify a record in a database. Using the id field is the most common - but if you've got another way to uniquely identify a user, then you can use that, too. Normally, you don't show a user what their ID number is in the database. But, if you want to give them a way to uniquely identify themselves, you could create another field which is unique for each user - such as a membership_number or similar. It seems like in your case, device_token is a field that uniquely identifies a user.
So, your database cares about the user_id field - that's what it uses to tie an Event to a specific User (aka, the owner). If your users knew their id, then they could pass in that, rather than their device_token, and everything would be fine. But they don't know it.
So, they pass in their devise_token. You use that to fetch the user from the database, and then you know that user's id. Then, you can store that user's id in the user_id field of your Event model.
def user
User.find_or_create_by(device_token: device_token)
end
This method is the one that gets a user based on a devise_token. And then this method:
def event_params
{
address: params[:address],
ended_at: params[:ended_at],
lat: params[:lat],
lon: params[:lon],
name: params[:name],
started_at: params[:started_at],
owner: user
}
end
In particular, the line: owner: user calls that method above. From that point, Rails handles it under the hood and makes sure your user_id is set correctly.
UPDATE AFTER YOUR COMMENT:
device_token is being passed in as a parameter. It is also the name of a field in the User model. So, a single row in the user table might look like this:
id: 24, first_name: fred, last_name: flintstone, device_token: 123abc, address: bedrock, etc.
the method:
def user
User.find_or_create_by(device_token: device_token)
end
is saying: go to the User's table in the database, try to find a User which has a device_token that has the value that was passed in as a parameter, and if we can't find one, then create one.
So in this line: User.find_or_create_by(device_token: device_token), the first reference to device_token is the key of a hash, and it refers to the field called device_token in your User model.
The second reference to device_token is a call to this method:
def device_token
params[:owner].try(:[], :device_token)
end
which fetches the device_token from the parameters passed in. This method basically says: Look in the params hash at the value inside the owner key. See if the owner key contains a device_token. If it does, return that device_token, and if it doesn't return nil. It does this using the try method, which you can read more about here: http://apidock.com/rails/Object/try
I'm trying to do a test send using
u = User.invite!({:email => "myemail#live.com", :name => "John Doe"}, User.find(1))
Why is Devise Invitable trying to insert into tables companies and company_roles with wierd/wrong values when I'm actually expecting only the user table to be updated.
This behaviour causes a ROLLBACK since the invite does not have the correct values to update these tables.
I only want to save stuff like company_role in the callback after the user has accepted an invite. How do I do this in the callback function and how do I access the initial values sent by the invite.
For example, can I do this?
u = #referrer.invite!({
email: params[:email],
title: params[:title],
first_name: params[:first_name],
last_name: params[:last_name],
website: #website,
company_id: #company,
country: #country,
}, #referrer)
And then later retrieve some of the values in the accept callback using this in the User model?
after_invitation_accepted :email_invited_by
def email_invited_by
# ...
end
I noticed that I can do a Model.find in a number of ways (assuming #user is an instance of the User model):
User.find(2)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user[:id])
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
OR
User.find(#user.id)
=> #<User id: 2, name: "Mike Swift", email: "valid#email.com", ... etc ...
Is there any real difference between the later three of these methods? (I already know User.find(n) would be the fastest) I would imagine they all work in about the same time, but perhaps I'm wrong.
In terms of sql they all do the same thing.
User.find(2)
This will be the fastest because there is no conversion needed.
Then User.find(#user.id) and User.find(#user[:id]).
And finally User.find(#user because rails needs convert the user to an ID.
User.find(2) should be faster as Rails doesn't have to do any work to figure out the id. The others require some level of message passing to get the id.
I doubt the difference is very significant though.
You could try all of them and look at your log to see how long it takes to get your response.