I have been working with jQuery token input and Rails 4.
Devise gem Application controller
devise_parameter_sanitizer.for(:account_update) { |u| u.permit( :email, :first_name, :last_name,
:password, :password_confirmation, :current_password, :passion_tokens => [] ) }
I want to save users :passion_tokens, but not able to save it. I have mentioned it in controller as per strong parameters.
user.rb
attr_reader :passion_tokens
def passion_tokens= (ids)
self.author_ids = ids.split(",")
end
So, please provide possible way to save the data.
attr_reader does not write to the attributes, which is the probable cause of your attributes not saving. You should use attr_accessor if you want to both read and write or attr_writer if only writing to attribute is required.
Related
I have this method
def create_billing_address(data)
address_data = data.permit(:first_name,
:last_name,
:phone,
:address_1,
:city,
:postcode,
:country)
service_customer.create_address(customer_id, address_data)
end
But now I want to check that all the keys are present. I tried to do this
address_data = data.require(:first_name,
:last_name,
:phone,
:address_1,
:city,
:postcode,
:country)
But require return an array instead of an hash.
How can I do to have the same behaviour of permit but with require ?
require is only intended to ensure that the params have the correct general structure.
For example if you have:
params.require(:foo).permit(:bar, :baz)
require lets us bail early if the :foo key is missing since we cant do anything with the request.
require is not intended to validate the presence of individual params - that is handled with model level validations in Rails.
If you really had to you could do:
def create_billing_address!(data)
keys = [:first_name, :last_name, :phone, :address_1, :city, :postcode, :country]
keys.each do |k|
raise ActionController::ParameterMissing and return unless data[k].present?
end
service_customer.create_address(customer_id, data.permit(*keys))
end
But thats just bad application design as you're letting the model level business logic creep into the controller.
permit and require are not interchangeable the way you think. If you establish that all the required keys are present, they still need to be permitted to be used in a mass assignment.
So you'd likely need to do...
def create_billing_address(data)
fields = %i(first_name last_name phone address_1 city postcode country)
address_data = data.permit(data.require(fields))
service_customer.create_address(customer_id, address_data)
end
The data.require will raise an ActionController::ParameterMissing exception if a key is missing, if not it will return the array of keys which can be used by permit.
Generally, what you want to do with require is more typically handled by model validation.
Documentation on require and permit is here...
http://api.rubyonrails.org/classes/ActionController/Parameters.html
I have a session controller which manages login/logout actions.These are not associated with any model. I want to use the validates helper methods with this session controller so that I can use, :maximum, :minimum, etc. conditions for the username and password. But if there is no model, how do I use these validation methods. Also, if I use these helpers it is easy to integrate with my simple_form login page for the error message, similar to which I have done for my user registration page.
If above helper methods are not possible to be used, what alternative I have which is easy to interface with my simple_form?
Validations can be used without creating a model, i.e. a class inheriting from ActiveRecord::Base. You can have a class that includes ActiveModel::Validations and use its methods. For example:
class Session
include ActiveModel::Validations
attr_accessor :username, :password
def initialize(user, pass)
#username = user
#password = pass
end
validates_length_of :username, minimum: 5
validates_length_of :password, minimum: 7
end
And you use like that:
session = Session.new("name", "secret")
session.valid? ## => false
I'm using Devise within my Rails app and I want to create a column where a user's pin number is stored (and is hashed).
The pin number is optional so it will be empty by default and changeable on the user settings page, provided by Devise.
I have the following code which works as expected:
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
end
I would add :pin_number as one of the permitted parameters in the account_update_params function, but how would I hash that and where?
I am a novice with rails so I would be grateful to be shown how to hash the parameter and then save it with the appropriate user.
You could use the bcrypt gem for this (Devise is already using this). In your create / update actions, you would have something that looks like this:
pin_number = BCrypt::Password.create("1234")
You'd then store pin_number in the database as is. When you retrieve it, you'd make a new Bcrypt::Password object like this:
hashed_pin = #user.pin_number
pin_number = BCrypt::Password.new(hashed_pin)
You could then compare a raw string to the BCrypt::Password objects with the == operator (the string will be automatically hashed before comparison):
hashed_pin == "1234" # true
In order to use this with your User model, you would need to add the field to your User migration:
# devise_create_users.rb
t.string :pin_number
You could then access it just like any other attribute of your model:
#user = User.find(1)
#user.pin_number = BCrypt::Password.create("1234")
#user.save
You can use attr_encrypted gem for this.
#user.rb
Class User < ActiveRecord::Base
attr_encrypted :pin_number, :key => 'a secret key'
end
And save encrypted version of pin_number in encrypted_pin_number field and call it like #user.encrypted_pin_number which returns the encrypted value of pin_number.
Rails newb, just working on my first app and my first coding experience outside of a little python and bash for sysadmin type work. Using rails 4.1 on C9 and kind of curious why I am experiencing a situation. From what I have read regarding using strong parameters, this replaces the old Rails 3 use of attr_accessible.
I am using devise and setup auth on my app, then wanted to add some custom fields like username and zipcode to be updated via a user profile page. Here is the code that I have to accomplish this. From what I have read the strong parameters should be moved from the model into the controller.
app/controllers/registrations_controller.rb # this inherits the devise::reg
def sign_up_params
params.require(:user).permit(:username, :email, :password, :zipcode, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:username, :email, :password, :zipcode, :password_confirmation, :current_password)
end
However, even after adding this it is still not saving the fields via my /users/edit page without the addition of the following.
app/models/user.rb
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :zipcode
Once the username and zipcode symbols (not sure of that is the correct term) have been added to the user.rb then the database is populated. The only thing I can think of is the fact that I added the gem 'protected_attributes' awhile back when trying to figure this out. Is this what is forcing me to use the attr_accessible statement in the user.rb?
If there is any additional code that would be useful just ask. Thanks for taking a look, it's much appreciated as I start to understand this.
I guess I should have just attempted this myself before asking here. I removed the gem 'protected_attributes' and commented out the attr_accessible line and restarted rails and viola, it still works. :D
In my User model I set validations for the password and its confirmation:
validates_presence_of :password, :password_confirmation
I use this for the forms. These attributes are not stored in the database, I am using the authlogic gem.
Now I am trying to make a system to restore forgotten passwords via email. The user inputs his email and the object is retrieved like this:
#user = User.find_by_email(params[:email])
Then, at a certain point in the process the value of a User attribute is set to true meaning that the user forgot his password, so I need to do a #user.save.
And there's the problem. Since password and password_confirmation were never stored, their values are nil. However, the validations come in play and prevent the user from being updated.
Is there any way to skip those particular validations so I can make this work? Or should I do something else? Any help?
You can skip all validations with save(validate: false). You can skip individual validations with the :if or :unless option, for example.
validates_presence_of :password, :password_confirmation, unless: :forgot_password?
def forgot_password?
# return true if the user is in the forgot password process
end
change
validates_presence_of :password, :password_confirmation
to
Assuming your field that is set to true is forgot_password
validates_presence_of :password, :password_confirmation, :unless => Proc.new { |a| a.forgot_password? }
Conditional Validations documentation