Where's the best place to put custom devise actions - ruby-on-rails

I've got a User resource generated by devise. The users have a has_many association with a model called Parking.
I need to create an action for listing all the parkings that belongs to a certain User. Without devise, I'd create a parkings action on users_controller, but I'm not sure how's the correct way of doing it devise-way.

You need to create a controller parkings_controller.Then In index method you can write your code to list all parkings that belongs to certain User.
like this ......
In your index method in parkings_controller.rb
def index
#parkings = current_user.parkings
end
Hope this will work for you.

Related

Rails 5 - Best way to hold onto params for creating associations?

Here's the scenario to illustrate my question. I have 2 models:
# models/post.rb
belongs_to :user
validates_presence_of :comment
And we have a devise model called Users
# models/user.rb
has_many :posts
What I would like to achieve:
Person comes to the website, is able to create a Post, after creating the Post, they are prompted to create an account. After creating the account, the Post that they just created would be associated to the User they just created.
Usually i'd make use of routes to hold the params[:id] which can be accessed in the controller method. For example the URL may look something like this:
www.foo.com/foo/new/1
And then I can do this:
# foo_controller.rb
def new
#foo = Foo.new
#parent = Parent.find(params[:id])
end
And in the view I can simply access #parent and use a hidden field to fill the parent ID.
But when routing through so many different pages (such as creating a Devise User), how do I hold onto the parent/child ID such that I can still create that association?
Using an hidden field or the route to store the id, with no authorization in the process, would not be secure. What if I just use the browser inspector and change the value of the id ? Your cool post would be mine.
What you could do is, for instance, add a field called guest_id to the Post, in which the value is unique (like SecureRandom.uuid), and also store that value in the session.
Thus, after the user is created, you could do something like that
if (post = Post.find_by(guest_id: session[:guest_id])).present?
post.update(user_id: current_user.id)
end

how can I create a form for User model which can be updated after successfully logged into application

Requirement: I need to create an application where user can logged in and can change the background color of that page, can change the font of the page and it should persist with session. so I am trying to create form which accept those attributes from user and can save in database. I am using devise for authentication.
How can I create form for user who is successfully logged into application(authentication is done by devise gem, so user table is already existing) and upon submission of form those attributes should get updated in user table. Any suggestion will be appreciated.
Q1 .What should be the name of controller and view for this form ?
Q2. How the routes can be define.
Q3. Whether controller should have update action to update user table with the extra attributes present in the form.
Thanks. Please comment below if I missed some information needed to provide. You can suggest me if you think this can be achieve in easier way also.
Whatever you want. Sounds li?ke you are just updated user attributes, so i would just use the User#update action
resources :users, only: [:update, :edit] #and any other user routes
? see 1
Also you will want to make sure that people can only edit their own account. In a before action you will want to add.
redirect_to root_path unless current_user == user_you_are_editing
What I would do:
Create a Model called UserPreferences that belongs_to :user, give this Model the attributes 'background_color', etc...
Add statement to user has_one :user_preferences
Create a form for the prefs like any Rails Model, that can only be accessed by current_user.
Use current_user.user_preferences to refer to these values, you can enhance this by placing alias methods in User, for example:
class User < ActiveRecord::Base
def background_color
self.user_preferences.background_color
end
end

What query do I perform to access the last of a collection of models before they have been saved?

I have a Workflow model, an Action model, and a Role model. Actions are nested attributes of a workflow, and an action has and belongs to many roles.
The associations work fine. However, in my form view, I need to add a role to the last action that has been build (note but not created).
The Workflow controller:
def create
#workflow = Workflow.new(workflow_params)
if params[:add_role] # from a submit button
Action.last.roles << Role.find(params[:role_id])
# doesn't work as no actions have been created
...
elsif params[:add_notify_action]
#workflow.actions.build # cannot save because parent hasn't been saved
end
In short, how do I get to the last Action that has been built in my controller? By definition, it's not in the database.
In long, if I can't, what's another option to get the roles added to the actions?
If an Action is a nested attribute of Workflow, when you initialize a new workflow passing the params, you initialize a new Action association. Then you could just go ahead and do:
#workflow.actions
to access the Actions. You cannot get the last one unless the Action has some attribute that defines that "last" characteristic (like a date given by the user). So consider saving them and then getting you can the last one by ordering them (created_at and updated_at fields). And before adding the persisted Roles, you'll need to also persist the action.
In the end, I decided to create a #current_action_id in my controller that I would update each time I called #workflow.actions.build. I ended up with this add_role method.
def add_role
unless #workflow.actions.empty?
#workflow.save!
role = Role.find(params[:role_id])
roles = Action.find(current_action_id).roles
roles << role unless roles.include? role or current_action_id <= 0
end
end
Thank you #engineersmnky for the tip on saving my workflow before adding the role.

rails fetching related data in page results

Supposing I have 3 tables: Users, Roles and UserRoles. I can fetch the user_roles in the request: users/1/user_roles but what if I want to fetch the roles of a user such as: users/1/roles.
My relation is as follows:
has_many :roles, :through => :user_roles
Is it possible?
The relation in your model has no direct relevance to the url you go to. You need to replicate your existing behaviour for routes rather than user_routes by either adding a new action or new controller and creating new views etc.
At the moment you probably have either:
an action called user_routes in the UsersController
an action called index in the UserRoutesController
So either:
Add an action called routes in the UsersController
Add an controller called RoutesController with an index action.
Regardless to which method you are using, in your action set your instance variable to user.roles instead of user.user_roles.
You can then write whatever view code you need.

Relation Between 2 Controllers

How can I define a relationship between two controllers. I have one controller called rides and another called registrant. Is there anyway I can access the registrant database from within the rides controller? I was thinking
#registrant = Registrant.find(:first)
from within rides, but that didn't work.
Any suggestions?
Thanks
You can access your registrant model from your rides controller just like accessing it from any other controller. What do you mean by Registrant.find(:first) not working?
Now, if there's a relationship (or association as it's normally called) between your rides model and registrant model (like a has_many association), you can use nested resources to nest one controller in another.
Check out the Action Controller Overview and Rails Routing from the Outside In guides and think about picking up a good book on Rails like Agile Web Development with Rails.
If you have defined models: ride and registrant (or more general user) then you can setup a before_filter on the rides controller:
before_filter :get_user
def get_user
#user = User.find(:first, :conditions => %Q(userid = "#{params[:user_id]}"))
end
This would fetch the the user with user_id passed in as a parameter before the controller generates the view.
Yes, that should work. To get the terminology right, you are accessing the Registrant model from the RidesController. They should both be in the same database, but in separate tables.
Please post the error message you are getting.

Resources