Adding "linked accounts" (e.g., Twitter, Facebook) to a Rails 3 website - ruby-on-rails

This isn't a question about how to use Twitter or Facebook API, but a simpler one about how to keep the databases in sync. What I want to do is to create a NEW linked account, and then attach that to the current user. I KNOW that my code currently is nonfunctional:
On the Edit Profile page
<%= f.label :account %> <i>(link another account to this profile)</i><br />
<% form_for #user.linked_accounts do |f| %>
<%= f.text_field :username %>
<%= f.collection_select :service, User::POSSIBLE_SERVICES, :to_s, :to_s,
:include_blank => true
%>
<%= f.submit %>
<% end %>
How do I get it to submit into a devise database? It's definitely the " form_for #user.linked_accounts " I need to fix. I changed it to #user and I get a no-method error because :service is only defined in a linked account. I think that what I need to do is to create a new linked account, and then do the form_for #user.new_account.
The error I receive is:
SQLite3::SQLException: no such column: linked_accounts.user_id: SELECT "linked_accounts".* FROM "linked_accounts" WHERE ("linked_accounts".user_id = 1)

There is a railscast that deals with this. It uses an authorisations table which belongs_to the user table so you can add twitter, facebook etc... to the user
The cast is over 2 episodes and uses omniauth which is a really neat solution. You can find them here
http://railscasts.com/episodes/235-omniauth-part-1
http://railscasts.com/episodes/236-omniauth-part-2

if i correctly understand your problem it's may be a solution for you to :
create a new model to contain social network information
use nested model to allow adding social via the edit user form
And that's it

Related

How to save data to multiple tables in Rails

I am using Devise for authentication in my app and got a model named as "Users". I created an another model for Company informations. I generated the migration with references and everything is okay.
I want to add user informations to users table and company informations to companies table in same registration view.
Also both users and companies tables got the same field as "name".
I tried to specify it as ;
<%= f.text_field :company["name"], autocomplete: "company_name" %>
<%= f.text_field :company[:name], autocomplete: "company_name" %>
<%= f.text_field :companies[:name], autocomplete: "company_name" %>
And i got the errors ;
undefined method `' for #<User:0x00007fd5588cb588>
no implicit conversion of Symbol into Integer
I think somehow i should override devise_controller but i want to learn the general practice for these kind of situations.
Sum: I want to save data to different tables which has same column names in database.
Assuming user belongs_to company and you want to save user and their associated company from one form submit, you can use fields_for for this
<%= f.fields_for :company do |cf| %>
<%= cf.text_field :name %>
<% end %>
This will require accepts_nested_attributes_for :company in User.

Rails Form - Check for pre-existing data and populate fields

I'm working on a rails app that allows field agents to report ticket(s) on behalf of clients. I am capturing the data using a model called "submission" where the agents can input the client's details and submit one or more tickets for the client.
I want to ensure that if a client already exists then a new record is not created for the same client. I would also like to ensure that if a client has a name similar to a pre-existing record then the clients don't get mixed up e.g: 2 people named John Smith.
My current submission form:
<%= form_for(#submission) do |f| %>
# some submission fields here ...
<h4>Client Details</h4>
<%= f.fields_for :client do |c| %>
<div class="row">
<div class="field col-xs-6">
<%= c.label :first_name %><br>
<%= c.text_field :first_name, class: 'form-control' %>
</div>
<div class="field col-xs-6">
<%= c.label :last_name %><br>
<%= c.text_field :last_name, class: 'form-control' %>
</div>
</div>
# more client fields....
<% end %>
<% end %>
How can I add a function to check for existing records that match the first and last names when you fill in the fields? Also, how can I ensure that if 2 clients exist with the same name then this can be identified? Could I maybe use the phone number as a unique identifier?
I know my question is a bit vague but I am unsure of how best to tackle this issue (autocomplete? maybe a checkbox that has options for new or existing client?)
Any help would be most appreciated.
You probably want to use Rails validations to ensure the first name and last name of client will not repeat. For example:
class Client < ActiveRecord::Base
validates :first_name, uniqueness: true
validates :last_name, uniqueness: true
end
But this will reject any that has same first name but different last name or the other case. In this situation you might search for custom validation method:
class Client < ActiveRecord::Base
validate :same_full_name
def same_full_name
# or different logic/additional condition
if Client.exists?(first_name: first_name, last_name: last_name, phone_number: phone_number)
errors.add("Client with this name exists.")
end
end
end
This will prompts error when user tries to submit the form. When Rails validation failed they will be redirected to this page(assuming that standard REST actions applied) and see the error message(if there's any flash or error message in your view).
If instant error prompt is preferred, you may want a JavaScript client integration with Rails validation such as client_side_validations gem, or use jquery validation for pure Javascript validation.
For the problem stated in the comment:
If a client does already exist in the database, how can I populate the form with this data and save the submission with the same client?
This depends on the web flow, another of the solution might be using ajax to call a controller action to check whether the client exists. If it does then you can use jQuery to populate the returned client data(from the controller) to the form, instead of doing the validation.

Rails Advanced Sign Up Implementation How To?

I am a three week old Rails newbie and I have something that I want to implement but have no idea how to go about it. I'm making an app:
I want a user to enter some sign-up info on the new users view page, then, when they click submit, instead of the user being created and saved in the database right away, instead I want them to be taken to a second webpage where they will be asked for some final verification before they can create their account. Then when they click 'verify' and the verification passes, the account is finally created and saved to the database.
This is hard for me because I only know how to make basic forms, where you enter info, hit submit, and you have a new entry in the database. I don't know how to defer the "user creation" for another webpage, but a friend has mentioned something about http requests, but I still don't know anything. I'll post some of my code so far:
My users_controller new definition:
def new
#user = User.new
#user.websites.build
end
My users_controller create method:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome!"
redirect_to #user
else
render 'new'
end
end
My users/new.html.erb sign up form:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<%= render 'shared/error_messages' %>
<%= form_for(#user) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %><br/>
<%= f.label :password %>
<%= f.password_field :password %><br/>
<%= f.label :password_confirmation, 'Confirm Password' %>
<%= f.password_field :password_confirmation %><br/>
<%= f.fields_for :websites do |builder| %>
<%= builder.label :url, 'Website URL' %>
<%= builder.text_field :url %>
<% end %>
<%= f.submit "Sign up", :id => 'submit' %>
<% end %>
I've never asked a question that's just asking for advice like this before, so I'm hoping this is the right place to ask. Any and all help is appreciated.
I think you are trying to create a "multistep" form...
There is a very good railscast about it: http://railscasts.com/episodes/217-multistep-forms?view=asciicast
However, you might face some validation problems, as you need to validate each step individually. So, take a look also here: http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation
I hope it helps...
You'd better use Devise for user management.
https://github.com/plataformatec/devise
Here's a railscast tutorial.
railscasts.com/episodes/209-introducing-devise
If you're doing multistep, you can always pass information from one page to another. You can store it in a session array, repost it to the other page, or even make a cookie.
Remember to also do every step of this under https, because account creation requires sensitive info.
If Rails is your first I would actually recommend something lower level like PHP so you can understand how everything works before you start doing stuff with a high level framework like rails. MVC is usually not the best first step in web development, even though it is powerful and easier than doing everything from scratch.

Rails 3 -- Pass user.id in hidden form field vs using association

Ok so currently I have a form
<div class="field">
<%= f.label :title %><br/>
<%= f.text_field :title %><br/>
<%= f.label :itunesurl %><br />
<%= f.text_field :itunesurl %><br />
<%= f.hidden_field :user_id, :value => current_user.id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
Which passes the current_user.id into the create method of my "app" model which creates it like this before saving it:
#app = App.new(params[:app])
However I have associations of (pseudocode)
user has_many apps
apps belongs_to user
Question: is it safer (so the form doesn't get modified) to do something like this within the create method?
#user = current_user
#app = #user.apps.create(params[:app])
If so... how exactly would I go about actually implementing the code above (its not syntactically correct.. just pseudo)?
Thanks!
Yes using the second way that you have suggested is the best approach
#user = current_user
#app = #user.apps.create(params[:app])
Also make sure you protect yourself from mass assignment, take a read of this http://stephensclafani.com/2010/01/04/ruby-on-rails-secure-mass-assignment/
It's absolutely safer to do it the second way. If you do it the first way, you're trusting the client to state who they are. Anyone could easily modify the form (with firebug, or they could manually submit a POST request with many tools) and end up submitting a form with the current_user of another person.
Make sure you apply this thinking everywhere throughout your app. Do not trust anything the client submits, ever.
The second code snippet is more "RESTful" than the first. By more RESTful, I mean, if an App is a resource that is logically accessed through a User, then by all means use it.
The way you set that up through routes:
resources :users do
resources :apps
end
This will give you paths like user_app_path and new_user_app_path, to which you pass a user ID and an app ID or a new app.
Hope this helps

how to handle multiple models in a rails form

http://weblog.rubyonrails.org/2009/1/26/nested-model-forms
This post helped in learning how to handle multiple models in a rails form. It works as long as the models are nested. what if they are not? lets say, I have a form, where the user fills personal details, address details and a bunch of checkboxes specifying her interests. There are at least 3 tables involved in this one single form, what is the best way to handle this, without having 3 different save buttons?
Two options:
First is ActivePresenter which works well for this.
Second is just to use fields_for:
<%= form_for #user do |f| %>
<%=f.label :name %>
<%=f.text_field :name %>
<%= fields_for #address do |fa| %>
<%=fa.label :city %>
<%=fa.text_field :city %>
<% end %>
<% end %>
Then in the controller, save the records.
#user = User.new(params[:user])
#address = Address.new(params[:address])
ActivePresenter works so well though.
Also found a railsforum post via Google, which would work well.
You can refer this tutorial by The Pragmatic Programmers
Advanced Rails Recipes

Resources