Ruby on Rails , Gem Devise Customization - devise

Hi i am currently working on my Ruby on Rails project and i wanted to customize the devise gem but my problem is that i cant seem to find some tutorials on how to customize devise more specifically customizing the login, parameters.
I already customized the login and the view of the device , but my problem is it doesn't seem to create the username , firstname , lastnamge , age , etc.
and it only gets the email and password etc. the basic stuff
i know the documentation is great and all specially because it is complete but my problem is that i find it a bit hard to follow specially when i cant see the video or how can i customize what i can put inside in the devise if anybody can help me with this , or any information on some tutorials with actually doing what i specified above that would be great and will really be appreciated , and please i am a bit new on RoR so i find it a bit difficult in just reading the text so i need some vdeo and thanks!
simplybel#simplybel:~/projects/gamification$ rails c
Loading development environment (Rails 4.1.6)
2.1.2 :001 > User.all
User Load (0.8ms) SELECT "users".* FROM "users"
=> #<ActiveRecord::Relation [#<User id: 7, first_name: nil, last_name: nil, profile_name: nil, email: "pat#yahoo.com", encrypted_password: "$2a$10$xg.HMU2JljnVLls3IX7Go.IfJVLGYSSRePjtDaYS4nE...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2014-12-01 23:50:17", last_sign_in_at: "2014-12-01 23:50:17", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2014-12-01 23:50:17", updated_at: "2014-12-01 23:50:17">]>
2.1.2 :002 >
this is the what the rails console returned after taking your advice, here is the code that you can clone
https://github.com/sanchez900/gamification.git
that is the code before I did the changes like the
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
i also did this
rails generate devise:views
also did the controllers
rails generate devise:controllers users
did the routes
devise_for :users, controllers: { sessions: "users/sessions" }
some other info might help also the project clone / link is before i did the modifications

If you had setup your view correctly to submit all the addition parameters, then you need to do as instructed in the docs https://github.com/plataformatec/devise#strong-parameters.
You need to update your permitted parameters on your sign up form to accept the new parameters you need. To do this, you can set a before filter to configure the permitted params for your devise controllers. Try something like this in your application controller.
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :profile_name) }
end
you need to explicitly write it as above (or use .push if you prefer)

Related

ActionController::InvalidAuthenticityToken in ActiveAdmin::Devise::SessionsController#create

I'm using Ruby on Rails 5 Api app with modification to enable Active Admin.
Everything was fine until now. I don't remember doing any changes in the app, but now, if I delete cookies and etc on the browser, I can't login to the active admin app and this error is what I get:
I tried to add in application controller both
protect_from_forgery :with => :exception
and
protect_from_forgery :with => :null_session
but none have worked.
This is my application controller:
class ApplicationController < ActionController::Base
# protect_from_forgery :with => :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
attributes = [:name]
devise_parameter_sanitizer.permit(:sign_up, keys: attributes)
end
end
I don't know what causing it and how to solve it.
Thanks beforehand.
Now it's working. After I restart my computer and added the line:
protect_from_forgery prepend: true, with: :exception
instead in the application controller, it worked.
It happens to me a lot when I switch from a branch to another without restarting my server.
Restarting the rails server works for me each time :)
In my context, I have a custom admin page and to solve I put a authenticity_token hidden field. Like below:
form method: :post, action: admin_templates_save_template_path do |f|
f.label "label", for: :base_proposal_url
f.input id: :base_proposal_url, name: :base_proposal_url
### field to handle authenticity token
f.input type: :hidden, name: :authenticity_token
f.button "Save", type: :submit
end

creating a custom path-helper while using FreindlyID

we're trying to get our site to have less scrapeable AND more readable urls
so e.g.
www.loomio.org/discussions/3122
becomes
www.loomio.org/d/3saA4ds9/lets-go-to-the-moon
we only really want the human-readable slug on show-links, so www.loomio.org/d/3saA4ds9/edit should be the url for editing that discussion
the solution so far follows the top answer here:
Ruby on Rails: How to override the 'show' route of a resource?
modify routes.rb:
get '/d/:id/:slug', to: 'discussions#show', as: :discussion
resources :discussions, path: 'd', except: [:edit, :show] do
get :activity_counts, on: :collection
member do
post :update_description
post :add_comment
post :show_description_history
get :new_proposal
post :edit_title
put :move
end
end
install gem FriendlyID; make and populated a :key column on Discussion table; add the following to discussion.rb (model):
KEY_LENGTH = 10
extend FriendlyId
friendly_id :key
write a custom path helper for group_path. in groups_helper.rb:
def group_url(group, options={})
url_for(options.merge(:controller => 'groups', :action => 'show',
:id => group.key, :slug => group.full_name.parameterize))
end
def group_path(group, options={})
group_url(group, options.merge(:only_path => true))
end
rake routes produces:
group GET /g/:id/:slug(.:format) groups#show
and while calling group_path(group) seems to work in some cases, I'm also seeing strange unrelated urls get generated, like :
http://loomio.org/group_requests/TegFOIx4DB/start_new_group?action=show&controller=groups%2Fgroups&slug=19-tory
in console, I'm also getting errors such as:
[5] pry(main)> g = Group.last
[6] pry(main)> app.group_path(g)
ActionController::RoutingError: No route matches {:controller=>"groups", :action=>"show", :id=>#<Group id: 2811, name: "Sylvester Buckridge", created_at: "2013-12-10 06:25:42", updated_at: "2013-12-10 06:25:42", privacy: "public", members_invitable_by: "members", parent_id: nil, email_new_motion: true, hide_members: false, beta_features: false, description: "A description for this group", memberships_count: 1, archived_at: nil, max_size: 300, cannot_contribute: false, distribution_metric: nil, sectors: nil, other_sector: nil, discussions_count: 0, motions_count: 0, country_name: nil, setup_completed_at: "2013-12-10 05:25:01", next_steps_completed: false, full_name: "Sylvester Buckridge", payment_plan: "undetermined", viewable_by_parent_members: false, key: "rkdlTytOin">}
from /home/s01us/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.16/lib/action_dispatch/routing/route_set.rb:540:in `raise_routing_error'
I've tried putting the group_path and grop_url methods in ApplicationController and ApplicationHelper to no avail.
calling
group_path( group.key, group.fullname.parameterize )
works, but would ideally like to be able to only have to call e.g.
group_path(#group)
as far as i understand the problem, you could use the good old hack with defining the to_param method on your model
class Group < ActiveRecord::Base
def to_param
"#{id}-#{slug}"
end
end
The beauty of this solution is that you won't need to do anything else. Rails will automatically use the to_param method as your record ID when it generates an URL from a record. You can do anything
redirect_to group_path(#group)
redirect_to #grup
# etc
and your Group.find should eat it as it is 123-smth-smth, usually it is smart enough to extract the integer part of the id

Ruby on Rails - CanCan user is nil during destroy action

I'm getting cancan with devise wired into my first Ruby on Rails app. I have some of it working, but I hit a problem my newbie brain cannot seem to understand.
I'm trying to delete a project model. The cancan ability.initialize call is not working because the user is passed as nil even though I am logged in and other calls successfully authorize
In my show view, I have this link:
<%= link_to "Purge this project", #project, method: :delete, data: {confirm: "There is no way to get it back. Are you sure you want to permanently remove this project?"} %>
I think my controller is wired up correctly, other actions are properly authorized
class ProjectsController < ApplicationController
load_and_authorize_resource
...
def destroy
puts "***********removing: " + params.inspect
#project.destroy
...
end
My cancan initialize does this:
def initialize(user)
user ||= User.new # guest user
puts "******** Evaluating cancan permissions for: " + user.inspect
...
When I click the delete link above, this gets puts'ed to the console (notice how user.id is nil, this is caused because i setup the guest if user is nil)
******** Evaluating cancan permissions for: #<User id: nil, email: ""...
Started DELETE "/projects/16" for 127.0.0.1 at 2013-04-04 10:48:23 -0400
Processing by ProjectsController#destroy as HTML
Parameters: {"id"=>"16"}
WARNING: Can't verify CSRF token authenticity
PROBLEM: Why is the user nil??? Is it related to the CSRF token issue? Is there something special about http method=delete that I'm missing? How can I stop the dumb, it hurts?
The preceding "show" action yielded this expected puts (concluding stuff should be wired up sufficiently):
******** Evaluating cancan permissions for: #<User id: 2, email: "doug...
Thanks!
self answer warning! So, I guess delete actions need to happen within a form post in order for the identity and CSRF stuff to be handled correctly?!?
Replacing my link with a form made things work again:
<%= form_for #project, :method => :delete do %>
<%= submit_tag "Purge this project", confirm: "Are you sure you want to permanently remove this project?" %>
<% end %>

ActiveRecord::AssociationTypeMismatch ruby 1.8 without using spork

I have models specs, controllers spec and request spec. When I run:
rspec spec
models spec are run first, then request and then when controller specs are run the specs for the first controller are OK, but the next fail. But when I run only the controller specs they all pass. I am with rails 3.0.9, ruby 1.8, factory_girl 2.2.0. I have
config.cache_classes = true
in test.rb and I can't change the version of ruby or factory_girl. Can someone help me?
UPDATE:
This is the error:
96) UsersController reset_password: as non-master_admin: does not reset a user's password
Failure/Error: let!(:user) { Factory(:admin_user) }
ActiveRecord::AssociationTypeMismatch:
AdminUser(#-630697398) expected, got MerchantUser(#-629918188)
# ./app/models/activity.rb:33:in `log'
# ./config/initializers/add_activity_logging.rb:8:in `_callback_after_759'
# ./spec/controllers/users_controller_spec.rb:8
in spec/controllers/users_controller_spec.rb:8:
let!(:user) { Factory(:admin_user) }
in activity.rb:33:
create(:user => user, :title => title, :changeable_id => changeable.id,
:changeable_type => changeable.class.to_s, :data => attributes)
also there is:
belongs_to :user, :class_name => 'AdminUser'
in the class AdminUser there isn't has_many activities but when I tried to add it I couldn't add it correctly I guess.
Thanks for the help
UPDATE:
AdminUser and MerchantUser are descendants of User
POSIBLE FIX
The line that gave error was actually:
admin_user = Factory(:tech_admin)
I replaced it with:
admin_user = FactoryGirl.build_stubbed(:tech_admin)
This way the file activity.rb is not reached
FINAL FIX
Apparently the problem was with Factory(:reseller). I replaced it with FactoryGirl.create(:reseller) and it everything work. Though now I am wondering and searching what is the difference between the two uses

Nested model not available in Devise views

I'm having a problem with associations not being available in my views.
My models are:
:user has_many :subscriptions
:subscription belongs_to :user
I'm using Devise to manage authentication etc. for Users
What I'd like to do: when creating a new user in the registration process, I also want to also create a subscription for that user.
Since Devise::RegistrationsController#new by default does not initialize an associated subscription, I've created my own RegistrationsController:
class RegistrationsController < Devise::RegistrationsController
def new
super
resource.subscriptions.build
logger.debug resource.subscriptions.inspect
end
end
The debug statement there confirms that a Subscription object is successfully created:
[#<Subscription id: nil, user_id: nil, chargify_subscription_id: nil, chargify_product_handle: nil, created_at: nil, updated_at: nil>]
The problem: in the view, resource.subscriptions does not exist.
If I inspect resource in the view, I get a User object that includes all of its own attributes but no associations (it should have an associated subscriptions)
debug(resource) gives the following:
--- !ruby/object:User
attributes:
name:
encrypted_password: ""
created_at:
updated_at:
last_sign_in_ip:
last_sign_in_at:
sign_in_count: 0 last_name:
current_sign_in_ip:
reset_password_token:
current_sign_in_at:
remember_created_at:
reset_password_sent_at:
chargify_customer_reference:
first_name:
email: ""
attributes_cache: {}
changed_attributes: {}
destroyed: false
marked_for_destruction: false
new_record: true
previously_changed: {}
readonly: false
Is there something I'm missing, or perhaps is there something strange about the resource mechanism used by Devise that prevents associations from being available in the view?
Thanks!
Edit:
If I just add resource.subscriptions.build in my view before rending the form, that works fine. But I think that kind of logic belongs in the controller and not the view, and I'd like to know what's keeping me from being able to put it there.
This answer is really late, but I found that if I override the entire controller action "new" (instead of delegating some of it to the parent with "super"), then I can build the resource properly. The reason is because "super" renders the view before handing control back to your custom controller method. Long story short...
class RegistrationsController < Devise::RegistrationsController
def new
resource = build_resource({}) # as found in Devise::RegistrationsController
resource.subscriptions.build
respond_with_navigational(resource){ render_with_scope :new } # also from Devise
end
end
Should work nicely...at least it did for me. Your code got me started on the right track anyway.