I'm a bit of a newbie at Rails and feel I'm missing a trick here. I'm trying to add a phone_number field to my Devise-generated User model, but I'm having an issue with saving it. I've done the rails generate devise:views, updated the edit.html.erb file to add in the :phone_number field, and created a migration to add the phone_number field to the model. It's not saving to the model because (as I understand it) I can't update the controller to include the new fields.
Do I need to create an app/controllers/users/registration_controller.rb defined with class Users::RegistrationsController < Devise::RegistrationsController and then monkey patch the update method? Or is there a more straightforward/elegant/easier way?
I realize there are a couple other questions related to this on the site, but one offers no useful answers, and the other simply details what I mention here. Is there anything more to it?
Thanks.
After you add the field to your database through a migration you will also need to add it to your list of accessible attributes in your User model. Your attr_accessible list should look something like the following depending on what devise modules you are using.
attr_accessible :email, :password, :password_confirmation, :phone_number
Related
Im building a membership web application with Ruby on Rails. I set up my DB and relationships between tables, everything worked fine. I decided to use Active Admin to shortcut the creation of a dashboard as well as providing a good search feature.
The issue I'm currently having is in Active admin on my dropdown list and table the foreign keys are only showing Id numbers and reference addresses (sorry, I forgot what their actually called).
Pics of my issue:
How can go about fixing this and in which files.
I would greatly Appreciate any help.
Customize ActiveAdmin Index Filters > Change The String Representation
Above article explains the similar issue. you have to do something like this in admin page for membership.
filter :plan, collection: -> {
Plan.all.map { |plan| [plan.name, plan.id] }
}
I have used name attribute for plan as an example. you may have different attribute, use correct attribute to reflect the details.
Update
Based on #DevOps92 answer
Alternate way to achieve this is to set any the method :display_name, :full_name, :name, :title, :to_s in Plan model
Active Admin Doc
For association columns we make an educated guess on what to display by calling the following methods in the following order:
:display_name, :full_name, :name, :username, :login, :title, :email, :to_s
This can be customized in config/initializers/active_admin.rb.
I solved the issue by going to my models that was generated by rails when I created the table in my database via scaffold. App/models/plan.rd and used the method display_name. Within the display_name method I listed the column name from the plan table. so anyone facing a similar issue check your rails models.
My Solution
This question is kind of hard to ask, but basically, I have a Class model and a User model, each Class table has a token, and so does each User one. After the user submits a sign up form, how would I set the value of the users class_id in the create action? I've tried <%= f.hidden_field :app_id, :value => App.find_by_token(params[:key]) %>, but this doesn't work. Sorry for the long and confusing question, will be glad to answer more. Thanks in advance for any answers
It sounds as though you have a "relationship" where a User belongs to a Class and a Class could have many users. If that is the case then you should use rails Associations to make it easy for yourself. This would involve adding a 'has_many :users' to your Class model and a 'belongs_to :class' call to your User model. You would then just use the rails helpers to 'build' the object and save it with the association in the corresponding controllers.
The manual way to do it would be as follows from your controller:
def create
#This would involve you sending the proper class id as a hidden form field with the form field attribute named 'class_id'. You may need to add 'attr_accessor :class_id' to your User model.
if user.create(user_params)
blahblahblah
else
sorry blah blah
end
end
private
def user_params
params.require(:user).permit(:name, :email, :class_id, :etc)
end
Normally you would use something like attr_accessible :name, :email to allow for mass assignment for those specific fields but how do you do this in mongoid for an embedded document like :nick_names? I tried tagging it at the end of attr_accesible but it does not work.
Thanks!
I would use a combination of criteria and update all. For instance:
Foo.where(country: nil).update_all(country: "USA")
http://mongoid.org/docs/querying/modification.html
If you're trying to do it via a Rails update, then #apneadiving is correct in that you need to enable accept_nested_attributes_for in the parent model.
I am developing a rails application in which I have two models User and Client.
User is backed by devise and is responsible for authentication and has_one Client which holds the client details for a given user. This relation is always present as I ensure that a Client model is created whenever I create a User.
For the administration area I am using ActiveAdmin. Now, when I try to create a User through the administration interface I use a form like this:
form do |f|
f.inputs :username, :email, :password
f.inputs :name => "Client", :for => :client do |client|
client.inputs :name, :address, ...
end
end
The problem is that either the User nor the Client are saved and the page is reloaded with validation errors. I have checked rails console and there's a WARNING: Can't mass-assign protected attributes: client_attributes message every time I try to create a User.
I have searched over this issue and found that in order to allow for mass-assignment one had to define attr_accessible for each of the fields allowed for the assignment. So, I had put this directive in Client model for each of the fields mentioned above and the message keeps appearing, preventing the models to be properly saved.
Does anyone have a clue on this?
The problem is not in your Client model, but in your User model - because this is the primary model you are trying to create. All you need to do is to add client_attributes to the list of attr_accessible attributes in your User model, just as the error message in the log files says, e.g.:
class User < ActiveRecord::Base
attr_accessible :client_attributes
end
I imagine you already have a list of accessible attributes in the User class. So just add client_attributes to the end of that list.
The changes you made to your Client model (i.e. adding a list of attributes to attr_accessible) is not needed for this to work. If you want, you can also go ahead and undo that.
I'm trying to figure out how to make this hack for attr_accessible to support a really common use case in my code, but really after looking at attr_acessible and ActiveRecord::Base source code for a while, still don't know where to start. I can probably figure it out after digging deeper, but first I'd like to ask if anyone else would find this hack useful, if there's some other way to do this right now,
Here's the use case:
For many models, the attributes that should be accessible through mass assignment are different when creating the object and when updating the object. One simple example is a User model that has two attributes: username, and password. When the object is just being created, I want both username and password to be accessible through mass assignment. After the object is created, only password should be accessible through mass assignment, because it shouldn't be possible to change the username.
Of course I could just set the username for the object manually in my controller's create method, but I find that some version of this case happens with every model. If it was possible to specify a different set of attr_accessible attributes for creates and updates, I could continue to use my standard restful new and create methods (for example as provided by inherited_resources). Besides I think this info belongs in the model.
So here's how I think it could work:
class User < ActiveRecord::Base
attr_accessible :password
attr_accessible_create :email
attr_accessible_update :bio
...
What would happen is that when the object is created, password and email would be accessible through mass assignment. When the object is updated, email and bio would be accessible through mass assignment.
This could also work through black listing via attr_protected. Same example with black listing:
class User < ActiveRecord::Base
attr_accessible :email, :password, :bio
attr_protected_create :bio
attr_protected_update :email
...
Or alternatively the syntax could be more like this:
attr_accessible :password, :create => [:email], :update => [:bio]
With these hacks, you can continue to use User.update_attributes(params[:user]) and User.new(params[:user]) in your controllers and know that the mass assignment stuff is taken care of. If your controllers are created by something like inherited_resources (which seriously rocks and keeps getting better) or resource_controller, you don't have to worry about creating custom controller actions for this simple, common use case.
The questions to you, my expert Rails users:
Is there a way to do this now that I'm overlooking, as a Ruby/Rails newbie?
Would you find this functionality useful, if it were supported?
Which syntax do you like better:
attr_accessible_update and attr_accessible_create
attr_accessible :update => [], :create => []
support both, dude!
Should I make this into a gem?
If you know where the parameters are sanitized during new/create/update/build with attr_accessible/attr_protected values, it would be great if you could point it out.
Thanks!
ActiveRecord has an attr_readonly method that should do what you need.
I'm pretty sure this kind of functionality doesn't currently exist.
If you go ahead and try to implement this as a gem, I'd probably be a bigger fan of the #2 syntax you proposed. As a general rule now, you can only use either attr_protected or attr_accessible in a model once, and you can't mix them. Adding more attr_* statements might get confusing.
Should you implement this as a gem? Why not? No harm in putting something else out there that at least you find helpful.
Sorry I can't help you on your last point. :)