rails 4 how to add custom form fields - ruby-on-rails

How can we add custom form fields in rails 4.
For ex:
User (model)
username
email
hashed_password
Now in the form field for password I would like to have fields like password and password confirm.
But due to the introduction of strong parameters in rails 4, I cannot simply send those fields .
It throws error.
It used to be a piece of cake in prior versions of rails i.e in the model we would add our custom form fields to attr_accessor and we could play with them.
NOTE: I tried this thing few weeks ago and it did'nt work, and I don't remember the exact error but was something like 'no method password on user'.
I know it is very stupid of me to not provide you with the exact error messages.
My apologies, can't help I deleted the application.
I was following this tutorial (it's for rails 3) http://www.sitepoint.com/rails-userpassword-authentication-from-scratch-part-i/

Check out How is attr_accessible used in Rails 4? for using strong parameters in rails 4
Protecting attributes is now done in the Controller.

I'm using attr_accessor in model in Rails 4.
In forms I have
<%= text_field_tag 'param_name' %>
And in controller
#model.param_name = params[:param_name]
It works ok and can solve your problem, I think. BUT! I'm not sure it is secure to use it this way. If someone can explain, why it is not appropriate for security reasons and suggest a better way, I'll appreciate it (as the author, I think).

Related

Ruby on Rails: How to validate if on specific page?

In my Ruby on Rails application I am trying to add in validations that will ensure the user has entered a value in a text box. In my system I have a table called Account which stores users' email account information, when they go onto the views/accounts/_form.html.erb page to add a new email account I want to validate the presence of a port number. I can do this through the following code:
validates :port, presence: true
This successfully ensures that users enter their port number, but when a user signs up through the views/users/_new.html.erb page they have to enter only an email address (e.g example#example.com) and the users_controller will then create a record in the Account table for this email address. My problem is that on the views/accounts/_form.html.erb page the port number is required but on the views/users/_new.html.erb it is not.
Is there a way of validating that the user enters the port number if they are on the views/accounts/_form.html.erb page or invoking the create method in the accounts_controller?
I am aware that I could do this through the HTML required validation like so: <%= f.text_field :port, :required => true %> but I need to add in further validation as well as presence, so this is not suitable.
You can create an attr_accessor field that determines if the validation should occur...
class Account < ActiveRecord:Base
attr_accessor :port_needs_validation
validates :port, presence: true, if: -> {port_needs_validation}
Then just set the accessor in your create method...
def create
#account = Account.new
#account.assign_attributes(account_params)
#account.port_needs_validation = true
if #account.save
...
Extract that part of the logic into a form object, check out the legendary 2012 blog entry from CodeClimate. Things have changed since then, the author uses Virtus to build form objects, more popular & up-to-date gems these days are:
reform
dry-rb
active type
but really you can make anything behave like an ActiveModel object
if it's a one-off thing, just do what Steve said in the other answer but that is a sure way to hell, safe-hate and divorce (at least from personal experience) in any slightly teeny weeny bigger project (i.e. you mean to spend some hours more working on it, it's not like you just finished everything and want to go home).
Actually, just use form classes everywhere and avoid model validations & other callbacks at all. You don't want things sending account activation mails or validating your password complexity when you're writing tests and just need a "post" that belongs to "user".
My own favorite personal fuckup due to model callbacks is sending 240.000 "your account has been upgraded/downgraded" emails because of an innocent spelling change update in an account_type attribute migration just because account_type_changed? was true.
So.. Form classes for ever, model callbacks never.
I would not recommend you have model aware of views. In #SteveTurczyn 's solution, an abstract field is introduced into model to identified the which page it come from, which is an good solution.
As from Ruby on Rail MVC, both View and Model talk to the controller, another solution will be have controller handle validation of params before passing the value to create account.

Prevent Devise from erasing entire registration form if a single field fails validation (Rails 4)

I have the same problem as the person in this post:
rails 3 + devise: if registration form has error, how prevent from erasing data in other fields?
That is to say, Devise erases the entire registration form after a single field fails validation. I am using rails 4, however, and therefore am not sure how to implement the "virtual attributes" solution given to the poster above.
Any help would be very appreciated.

Can anyone show me how to make "Mailboxer"'s controller, model, view, and routes?

First of all, thanks in adavance.
This might be so noob question.
I already did setup devise and mailboxer. devise works completely fine!
Then "username" column is added to Users table, and I configured just like this
/config/initializers/mailboxer.rb
#Configures the methods needed by mailboxer
config.email_method = :email
config.name_method = :username
Now I'm totally stucked!! I don't know how to make the rest for simple message system.
What I want is these message function listed below
index(index/received or index/sent)... you can see the list of messages received(from/to, subjectes, and received date are only shown)
show...you can see whole body of the message.
new... message create form, as an option, you can choose 'reply' from "show" page. in this case body text field already includes messages quotes.
Can someone make very simple example for me?
I can pay up to $50 for it via paypal!
I think I need to make
"messages_controller"
"message" model if you needed with mailboxer gem
"view/messages/index", "view/messages/show", "view/messages/new"
"routes" has to be modified.
Thanks
I assume you've resolved your issues by now, but for future reference, a sample app featuring the mailboxer gem is:
https://github.com/RKushnir/mailboxer-app
(not mine, but helpful to get up and going)

Is there a way in Rails to say "run all the validates EXCEPT :password"?

I am using Devise for my authentication. If a hashed_password isn't set, Rails/Devise's validations will require a password to be set, as well as the password_confirmation.
When I invite new users, I obviously don't want to set their password, so when I create the invitation in my system, it fails because user.password is blank.
I can set a temporary hashed_password on the user, but when they enter their own password, the validation checks for :password and :password_confirmation will not happen because hashed_password is set, which is a real problem.
Is there any way to tell Rails that I want to run all the validations except for the ones associated with :password?
I know Rails has :if conditions, which might fix my problem, but Devise declares the :password validation on my behalf, so that essentially is hidden.
How can I get the desired result here?, hopefully in a way that is not a hack.
My current hypothetical solution that is somewhat messy: The only thing I can think of is to create a new Invitation model that is not the User model, and use the Invitation model for the form. When the invitation is submitted I can validate that Invitation and copy over all the values to the new User model. I can save that User without any validations at all.
That's the best solution I dreamed up.
It seems like my solution will be a lot more work than saying something simple like:
user.save(validations => {:except => :password})
EDIT: I have found one part of the solution, but I am still having problems. In our user model, we can override a Devise method to prevent the validation of the password for invitations with this bit of code:
#protected
def password_required?
!is_invited && super
end
The is_invited attribute is just a column I added to the users table/model.
However, there is one gotcha here. When a user accepts an invitation and they arrive to the form where they need to set their password/password_confirmation, valid? will always return true.
This one has me deeply perplexed. I don't see how requires_password? and valid? can be true at the same time. If it requires the password, it should do a validation check and cause the validations to fail.
I'm starting to hate Devise - or just the idea of using gems to build parts of your application in a blackbox. I think the real solution probably is to rip out Devise and just do it all from scratch. That way your app has total control of how all of this works :(
I recently started using this great devise add-on: devise_invitable
It's commonly used so users (or any model) can invite other users to join.
But I adapt it for manually (via an admin panel) invite new potential users to my app.
Hope this helps!

Rails 3.0 Devise reset Password by answering a question

I am using devise with rails 3. In user model I have created fields for the question and answer to that question.
I want to know How I can implement forget password in following logic:
On forget password page User enters the Username
On Next step application should displays the question stored in db.
User answers the question and app matches the answer if answer is matched with values stored in db.
It redirects to edit password page where password can updated.
I tried to override password controller of devise but got stuck.
Thanks for help in advance.
Note: I am new to rails and its my first project
I've actually not used Devise before, however assuming you have a befor_filter on your controller to route to Devise authentication, you could possibly do something like:
skip_before_filter :authenticate_with_devise if user_answered_question_correctly?
this gem has a security_questionable feature which would do the trick, amongst other things https://github.com/phatworx/devise_security_extension
You don't need to override Devise for this.
make your own forget_password routes:
in routes.rb:
get "forgot_password" => "passwords#forgot"
get "forgot_password/verify_question" => "passwords#verify_question"
post "forgot_password/verify_answer" => "passwords#verify_answer"
post "forgot_password/reset_password" => "passwords#reset"
Create app/controller/passwords_controller.rb and fill out logic you want via forms / render.
Create views.
Change forgot password link to your own.
Profit

Resources