I have a controller, I need to merge one column that is not there in database. Actually that column name I should not add in db and I should not add migration for this.
This is my create action:
User.new(user_params).merge(first_name: "xyz")
This is my user_params method:
def user_params
params.permit(:id, :name :email_id)
end
but merge is not working. Could any one help me in this. Thanks in advance.
You can merge first_name to the params or set it after initiated the User
def user_params
params.permit(:id, :name, :email_id).merge(first_name: 'xyz')
end
or:
user = User.new(user_params)
user.first_name = 'xyz'
Edit: If User table does not have the first_name column you can't do what you want
You can use active storage and give relation like user has_one:first_name and you can add first_name without adding it in your user model/table
def user_params
params.permit(:id, :name :email_id)
end
You use merge for user_params.
User.new(user_params.merge(first_name: "xyz"))
Related
I have a legacy rails application that has some security issues I am trying to fix.
In particular it is saving from a post using:
#user.update_attributes(params[:user])
I want to make sure that when saving, one of the attributes is explicitly set in the controller. There is a variable:
#company
I want to make sure the user.company_id has the value from #company variable before the call to update_attributes.
You can merge into params at the controller if you want.
user_params = params[:user].merge(:company_id => #company.id)
#user.update_attributes(user_params)
The merge will ensure any company_id in the params gets overwritten
just update the user params along with company_id by trying something like this.. it is always advisable to whitelist params by defining pvt method..
def user_params
params.permit(:user)
end
#user.update_attributes(user_params.to_h.merge!({company_id: #company.id}))
If company_id is not present in params[:user] then you can set comapany_id using before_filter in the controller as:
before_filter: set_company_id
private
def set_company_id
##Assuming you have the #user and #company objects before using
#user.company_id = #company.id
end
so after when you execute:
#user.update_attributes(params[:user])
#user object will have all the desired attributes saved...
I have a template, a user and user_templates. user has many templates through user_templates.
Currently, whenever a new template is created a user_template record is created as well. This works perfectly with creating 1 record.
Template Create Controller:
def create
#template = Template.new(template_params.merge(user: current_user))
if #template.save
save_user_templates(current_user.id, #template.id)
redirect_to dashboard_url
else
render(:new)
end
end
Save User Template function
def save_user_templates(user, template)
UserTemplate.create(user_id: user, template_id: template)
end
Now I want to implement a 'Multiple Select' so I can select multiple users, click save, which would then create a record for each user in the user_template table at once.
My idea is to pass an array from the view to the controller and then loop through that array and save each record before redirecting. Question is: How do I do that?
Figured out a solution after trying various things. Unfortunately, I did not see the reply in time. Here is what I did.
View
.form-group.has-feedback
.text-muted
= f.label 'Which users should see this?'
= f.collection_select :user_templates, User.all, :id, :name, { include_hidden: false }, multiple: 'true'
Controller
def create
#template = Template.new(template_params.merge(user: current_user))
if #template.save
save_user_templates(params[:template][:user_templates], #template.id)
redirect_to dashboard_url
else
render(:new)
end
end
def save_user_templates(users, template)
users.each do |user|
puts user
UserTemplate.create!(user_id: user, template_id: template)
end
end
You could iterate over the array of users and perform the same action on each of them.
def save_user_templates(user_id_array, template)
user_id_array.each { |user_id| UserTemplate.create(user_id: user_id, template_id: template) }
end
I have following code in the controller:
def create
#company = Company.new(company_params)
....
end
private
def company_params
params.require(:company).permit(...list of columns...).merge(latlng: geocode)
end
I would need to save to the database the column called slug. The value of this column would be
slug = params[:company][:name].parameterize
The column slug is not mentioned in the permit list. How to add & save this information to the database?
Thanks
def blog_post_params
params.require(:post).permit(:title, :author, :published, :body)
end
class Contact < ActiveRecord::Base
attr_accessor :email
def initialize(data)
data.each { |k, v| send("#{k}=", v) }
end
end
In rails console
Contact.create!({"email"=>"foo#gmail.com"})
The record saved to the database has email as nil
Update:
The data is being passed in is JSON. I am getting all the data from the JSON and trying to save that into the database.
Did you try:
Contact.create!(email: "foo#gmail.com")
The email as a :symbol and no curly brackets?
Also, why are you initializing in your model?
With Mohamed El Mahallaway, I think your code setup could be improved (to negate initializing your model). I think you'll be better using the strong_params functionality of Rails:
#app/controllers/contacts_controller.rb
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
#contact.email = "foo#gmail.com"
#contact.save
end
private
def contact_params
params.require(:contact).permit(:email, :other, :params)
end
I may have miscalculated your competency with Rails, but this is the "Rails" way to save the correct data to your model :) You may to have a before_save method in your model to use the email attribute, considering it's a virtual attribute
I have first_name and last_name fields currently represented in my model in rails. I'd like to add another field to my database called full_name and was wondering what the best way to do this seamlessly would be. Mind you I also have a production server going and would like to make it so that I not only add a column in my migration, but also can populate the new field with the existing data.
EDIT:
Here's my controller
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
#followers = #user.followers.find(:all, :select => 'users.id, users.first_name, users.last_name', :conditions => ["users.first_name like ?","%" + params[:q] + "%"])
respond_to do |format|
format.html {render 'show_follow'}
format.json {render :json => #followers}
end
end
I want to be able to 1. select: 'users.id, users.full_name and 2. :condition =>["users.full_name like ?", ...] and the only way I can think to do this is to modify the model. I also only want to return the properties id and full_name in the json object.
You will probably be better off just defining a full_name method in your model:
def full_name
([first_name, last_name] - ['']).compact.join(' ')
end
You can search by full name with something like:
def self.find_all_by_name_containing(text)
self.where("LOWER(first_name || ' ' || last_name) LIKE ?", "%#{text.downcase}%")
end
Then define your own #to_json
If you really want to go ahead with adding a full_name field to your User model, then I suggest the following steps.
1.Generate a rails migration adding the field full_name to users table.
rails g migration add_full_name_to_users full_name:string
2.Add the following before_save callback to your User model.
Class User < ActiveRecord::Base
...
before_save :set_full_name
private
def set_full_name
self.full_name = "#{self.first_name} #{self.last_name}".strip
end
end
3.Commit, push code to production, run migration on production.
4.Run a save or save! method on all your users in rails console.
$> User.find_each(:batch_size => 1000){ |user| user.save }
I guess, that should take care of updating your existing users, plus the before_save call will take care of future additions/updates.
Generate migration
rails g migration add_full_name_to_users
Inside migration:
def up
add_column :users, :full_name, :string
execute <<-SQL
UPDATE users SET full_name = first_name||' '||last_name WHERE full_name IS NULL;
SQL
end
It will create full_name column and populate it with default data. You can also do something like this in ruby but it will be much faster in SQL.