Ruby on rails Landing Page - ruby-on-rails

I have an extremelly basic rails 4 application. It's like a landing page with a video embeded from youtube and with a field for the user put his email and zipcode...
So, I am having trouble to save this user's email and zip code, actually, I am new at rails and I don't know how to do it... I have created a model called Information, with an email and zipcode(both strings)... I have a view called home with this code:
<%= form_for :information do |f| %>
<div class="form-group">
<%= f.label :Email_address %>
<%= f.text_field :email, class: "form-control", :autofocus => true, placeholder: "Enter email" %>
</div>
<div class="form-group">
<%= f.label :Zip_Code %>
<%= f.text_field :zipcode, class: "form-control", :autofocus => true, placeholder: "Zip Code" %>
</div>
<div class="form-group">
<%= f.submit "Submit", class: "btn btn-danger" %>
</div>
<% end %>
But when I click submit nothing happens, I think I should create a controller but I dont know what to put on it to make it work! What should I do to collect just this two information in the best way? Thanks very much!

You will need controller with two actions: :new and :create.
in console rails g controller informations (I assume your model called Information).
In this file
def new
#information = Information.new
end
def create
#information = Information.new(information_params)
redirect_to #information
end
private
def information_params
params.require(:information).permit(:email, :zipcode)
end
And then this code should go into /view/informations/new as new.erb
<%= form_for #information do |f| %>
<div class="form-group">
<%= f.label :Email_address %>
<%= f.text_field :email, class: "form-control", :autofocus => true, placeholder: "Enter email" %>
</div>
<div class="form-group">
<%= f.label :Zip_Code %>
<%= f.text_field :zipcode, class: "form-control", :autofocus => true, placeholder: "Zip Code" %>
</div>
<div class="form-group">
<%= f.submit "Submit", class: "btn btn-danger" %>
</div>
<% end %>
And take a look at some quick tutorial to have a basic understanding of how MVC established. This guide http://www.railstutorial.org/book is what almost everyone start.

Let me explain some things for you, as you're new
Objects
Ruby (& Rails by virtue of being built on Ruby) is object orientated. This means that every interaction you make with the Rails backend (the landing page doesn't interact with the backend initially), has to be centred around objects
Although you've done well by creating the respective objects (with the Information model), you need to appreciate the process of creating, populating & initializing the respecting objects
--
Form
You're using form_for requires an ActiveRecord object. This is your major downfall - say your landing page is at application#welcome, here's the
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
def welcome
#information = Information.new #-> creates "information" object
end
end
The form_for method can then take the #information object, to populate the data as required:
#app/views/application/welcome.html.erb
<%= form_for #information do |f| %>
<%= f.text_field :email %>
<%= f.text_field :zipcode %>
<%= f.submit %>
<% end %>
Notice how you're using the #information object here? This is where the ActiveRecord object comes in - allowing you to "populate" that as you wish
--
Backend
#config/routes.rb
root: "application#welcome"
resources :information, only: :create
The form_for will send your request to information_controller.rb:
#app/controllers/information_controller.rb
Class InformationController < ApplicationController
def create
#information = Information.new(information_params)
if #information.save
flash[:notice] = "Message Sent - Thank you!"
redirect_to "application#welcome"
end
end
private
def information_params
params.require(:information).permit(:email, :zipcode)
end
end
This will be able to take the #information object, populate it in the database, and then redirect to the original "landing" page again.

Related

How can I redirect with submit button in rails?

I have this HTML:
<% provide(:contact, "active") %>
<% provide(:title, "Contacto | Recotiendame") %>
<div align="center">
<h1 id_"page_title">Contactanos!</h1>
<div class="skinny_wrapper wrapper_padding"
<%= form_for contact_path, url: #done do |f| %>
<%= f.label :Nombre %><br>
<%= f.text_field :Nombre, required: true %>
<br>
<%= f.label :Email %><br>
<%= f.email_field :Email, required: true %>
<br>
<%= f.label :Mensaje %><br>
<%= f.text_area :Mensaje, as: :text %>
<div class= "hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint: 'dejalo en blanco' %>
</div>
<br>
<%= f.submit 'Enviar Mensaje', class: "button" %>
</div>
<% end %>
</div>
with this controller:
class ContactController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
#contact.request = request
if #contact.deliver
flash.now[:notice] = 'Gracias por su mensaje. Lo contactaremos luego!'
else
flash.now[:error] = 'No se pudo enviar el mensaje.'
render :new
end
end
end
The problem is that the submit button does nothing. How can I make it work to redirect me to create? I have seen lots of answers to this question but none works for me.
EDIT 1
When I did #done, it was only to try things.
If I had to guess, I think you've got your form_for fields wrong. Normally you'd have something like: form_for #contact and it'd Just Work, but if you wanted to override the default url, you'd pass a different url eg
form_for #contact, url: contacts_path`
(note the plural is important).
I don't know what #done is meant to be... but it probably shouldn't be there... and putting the contact_path has two incorrect things about it:
1) you shouldn't have a url at that point, but an object (in this case the object is the contact)
2) contact_path is for showing a single contact that has already been saved, for creating a new contact, you need contacts_path (the idea is that you're posting a new contact to the set of contacts).

modal form not creating user

I have created forms in rails with no problems before, but this is my first time doing it in a modal and I am not sure if that effects things. I don't think it does, but you never know. The problem is that new users are not being saved, and I am getting no useful errors as to why. Here is my form, in the modal:
<div class="modal-body">
<%= form_for #user do |f| %>
<%= f.label :first_name %><br>
<%= f.text_field :first_name, class: 'form-control', :required => true %><br>
<%= f.label :last_name %><br>
<%= f.text_field :last_name, class: 'form-control', :required => true %><br>
<%= f.label :user_name %><br>
<%= f.text_field :user_name, class: 'form-control', :required => true %><br>
<%= f.label :password %><br>
<%= f.password_field :password_digest, class: 'form-control', :required => true%><br>
<%= f.label :password_confirmation %><br>
<%= f.password_field :password_confirmation, class: 'form-control', :required => true%><br>
</div> <!-- modal body -->
<div class="modal-footer">
<%= f.submit "Sign Up"%><br>
</div>
<% end %>
and here is what is in my users controller:
def create
#user = User.create(user_params)
if #user.save
redirect_to root_path
else
redirect_to({:controller => 'application', :action => 'home'}, :notice => 'Account not created! Something is fishy.')
end
end
def user_params
params.require(:user).permit(:first_name, :last_name, :user_name, :password)
end
More than likely, I am missing something. My question is two part: A)what is wrong and B)how can I stop the modal window from closing and have it display the appropriate error to the user giving them a chance to fix it?
Try:
#user = User.new(user_params)
instead of:
#user = User.create(user_params)
Because, you are trying to save the user after this call.
When you use create, it calls create followed by save.
If you use: User.new(user_params), it will just load the user object with the specified user_params but will not save it. In the next line, when you call: #user.save then the user object will be saved if valid. Otherwise, not.
Also, you can try using: #user.save! instead of #user.save. Because, when you try to save an object using save! method, it will raise an exception if it can't save the object properly. That way, you will know if something went wrong.
Observe the elements/tags "" should inside form_for becuase closing tag is inside of it.
<%= form_for #user do |f| %>
<div class="modal-body">
......your stuff fields here
</div> <!-- modal body -->
<div class="modal-footer">
<%= f.submit "Sign Up"%><br>
</div>
<% end %>

RoR: Forgot Password & Sign In - in same page

I'm trying to put Forgot password field with the sign in page, but if user is not registered (and not in apps database), then it redirects to the original devise Forgot password page with errors (http://localhost:3000/users/password). How do I make the errors appear in the same page as the sign in page (http://localhost:3000/users/sign_in)?
In app/views/devise/sessions/new.html.erb file
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= f.email_field :email, required: false, autofocus: true, placeholder: "Username" %>
<%= f.password_field :password, required: false, placeholder: "Password" %>
<%= f.button :submit, "Sign In", class: "btn btn-success btn-sm" %>
<div class="remember-forgot">
<div class="row">
<div class="col-md-6">
<%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
</div>
<div class="col-md-6 forgot-pass-content">
Forgot Password
</div>
</div>
</div>
<% end %>
<!-- where reset is -->
<div class="pass-reset">
<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), namespace: 'forgot', html: { method: :post }) do |f| %>
<%= f.error_notification %>
<label>Enter the email you signed up with</label>
<%= f.email_field :email, required: true, autofocus: true, placeholder: "Email" %>
<%= f.submit "Submit", class: "pass-reset-submit btn btn-success btn-sm" %>
<% end %>
</div>
So there's a javascript link where an input field will show up if a user forgets their sign in credentials.
apparently two forms for same object having same fields should not be one page, one should stay with the new page. but still i have tried your question, and following things needs to be done
1) I have to override the passwords controller for devise under user scope.
class Users::PasswordsController < Devise::PasswordsController
# GET /resource/password/new
def new
super
end
# POST /resource/password
def create
self.resource = resource_class.send_reset_password_instructions(resource_params)
if successfully_sent?(resource)
flash[:notice] = "sent password"
redirect_to :root
else
render "devise/sessions/new"
end
end
# GET /resource/password/edit?reset_password_token=abcdef
def edit
super
end
# PUT /resource/password
def update
super
end
protected
def after_resetting_password_path_for(resource)
super(resource)
end
# The path used after sending reset password instructions
def after_sending_reset_password_instructions_path_for(resource_name)
super(resource_name)
end
end
then my devise/sessions/new page will look like this(you can add the logic of showing form only when one clicks he forget password button. that should be simple. just add hide class and on click remove hide class.)
Log in
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<% if devise_mapping.rememberable? -%>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end -%>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
#assuming that devise_mapping has recoverable? option. you can also keep the below form in if condition
<h2>Forgot your password?</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), namespace: "forget", html: { method: :post }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="actions">
<%= f.submit "Send me reset password instructions" %>
</div>
<% end %>
need to tell the routes to use my my passwords controller.
devise_for :users, controllers: {
passwords: 'users/passwords'
}
These things will result in showing the errors under the user sign in form but the path will remain http://localhost:3000/users/password. why because we are rendering the page and not redirecting. render just show the views without going to the controller action. now even if one tries to send the errors messages to the sessions controller somehow(after overriding that controller as well) somehow like this
redirect_to new_user_session_path, :messages => resource.errors
still that wont help, why because in session#new we are re initializing the resource as it is new action and all the errors would be gone.
I'm not sure if this is satisfactory to you or if this is not even close to your requirements. i tried to cover all things. i would be glad if some credible or official sources will provide even better response. that would definitely increase my knowledge as well.

edit link for "admins" in devise rails

I have a rails app using devise for registrations and rolify for roles. I would like to have an index page that has edit links for each of the users that can be accessed by an admin. This edit page should also work without having to use a password. Right now the edit_user_path goes to the edit page of the current user, which is not what i want.
What is the best way to implement this sort of sitation? i've read a few of the posts on here about this but none seem to give me what i want.
Please point me in the right direction!
EDITED
I'm attempting to do it this way, still running into "Current password can't be blank"
From Users_controller:
def update
#user = User.find(params[:id])
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
if #user.update_attributes(user_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
And in my views i have an edit.html.erb file that is rendering the following form:
<div class="panel-body">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: "form-control", :autofocus => true %>
</div>
<div class="form-group">
<%= f.label :username %>
<%= f.text_field :username, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :firstname %>
<%= f.text_field :firstname, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :lastname %>
<%= f.text_field :lastname, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :city %>
<%= f.text_field :city, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :zip %>
<%= f.text_field :zip, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :state %>
<%= f.text_field :state, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :country %>
<%= f.text_field :country, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Update", class: "btn btn-primary" %>
</div>
<% end %>
</div>
and finally in my routes.rb file i have this line to render the edit page. I can get the edit page to show up but entering info and then hitting update just shoots me to /users with the error "Current Password can't be blank"
get 'pressroom/accounts/:id/edit' => 'users#edit', :as => :admin_edit_user
Devise doesn't come with any sort of Admin interface. If you are the only administrator and don't mind a little crudeness - there is always the console and/or scaffolding. You could create a UserController which inherits from ApplicationController and execute basic view, edit methods in the same controller. By placing the appropriate new.html.erb, edit.html.erb etc files in the User Views folder, adding/editing/deleting Users should work no differently as any other CRUD, as Devise's User is another model like any. Use a scaffold on the user and you could get what you are looking for.
There are also a lot of good gems that make setting up admin interfaces a cinch: https://github.com/gregbell/active_admin Active Admin, https://github.com/sferik/rails_admin Rails Admin and I'm sure there are a bunch more out there.
It looks like i got it working by adding:
<div class="panel-body">
<% #user = User.find(params[:id]) %>
<%= form_for(#user) do |f| %>
to the top of my _form.html.erb file
Thanks for the help everyone!
If the only thing you need is for the admin to EDIT an existing user, you can have the edit, show and update actions in a separate UsersController (and leave new and create actions up to devise). That way you can move that #user = User.find(params[:id] logic out of your form, into the controller, as #Saurabh Lodha mentioned.
I just thought one thing was missing from the answers though: Make sure to also edit your routes.rb. Use a path prefix so your routing doesn't get confusing, kind of like this:
devise_for :users, :path_prefix => 'my'
resources :users
this means that when you call edit on a current_user, it will go to my/users/edit, and when you call edit on any selected user from your user list in the admin panel, it will take you to users/user_id/edit.
I hope that clarified it a bit more! good luck! :)

Virtual attribute allways nil in custom validation method

because I'm pretty new to Ruby on Rails I'll explain what I did. I've got a virtual attribute in my model called testing. I've defined it like this:
class Comment < ActiveRecord::Base
attr_accessor :testing
attr_accessible :user_name, :comment, :user, :testing
I then added custom method for custom validation like this:
validate :custom_validation
I also added the method, of course:
def custom_validation
# a bit of custom_validation
end
I then added a field in my form:
<%= form_for(#comment) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= f.hidden_field :post_id, :value => #post.id %>
<% if !signed_in? %>
<div class="field">
<%= f.label :user_name %>
<%= f.text_field :user_name, :class => "user_field" %>
</div>
<% else %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<% end %>
<div class="field">
<%= f.label :comment %>
<%= f.text_area :comment, :style => "height: 50px; width: 80%;" %>
</div>
<div class="field pin">
<%= f.label :testint %>
<%= f.text_field :testing, :class => "user_field" %>
</div>
<div class="buttons">
<%= f.submit "Speichern" %>
</div>
<% end %>
That's all I did. So please don't assume I did something else I didn't describe here, because I didn't ;)
My problem is, that my virtual field testing is always nil inside of my custom_validation method. Unless I run the validation in the console:
co = Comment.new
co.testing = "Hello"
co.valid?
I've checked using the logger. If I run via the console the testing-field isn't nil. If I run it via the browser, it is. It seems that the parameter is somehow not passed to the model correctly. I hope I just missed something really obvious. Hope you can help me.
Cheers,
Michael
It has to do with what's in your create or update actions. The scaffold generator will put in code to set real attributes, but does not call setter methods from attr_accessor.
add attr_reader :testing to your model!

Resources