Rails: update custom attribute by re-rendering partial via AJAX - ruby-on-rails

I have a custom field phone for a User that is not stored in the database, since I'm using it for other purposes. Each field is in a different partial and can be updated on it's own via AJAX. This is how I handle this in the UsersController:
app/controllers/users_controller.rb
def update
#user = ...
if #user.update_attributes(params[:user])
respond_to do |format|
format.json { render json: {html: render_to_string partial: 'edit_field', locals: { user: #user }} }
end
end
end
I have the submitted phone param available in a custom User model attribute custom_attrs:
app/models/user.rb
include UserConcern
...
attr_accessor :custom_attrs
...
# I've shorten this method, so that you can get the idea, might not work in reality
def update_attributes
self.custom_attrs[:phone] = self.phone
end
I can't add that to the #user object before I return the response in the controller, I get ActiveModel::MissingAttributeError: can't write unknown attribute 'phone'.
In my view the phone field value is set by a method in the UserConcern:
app/models/concerns/user_concern.rb
def phone
self.phone = fetch_phone(user) # this method returns the users' phone value
end
When I update the phone and re-render the partial, it still has the same value, because the #user object doesn't have phone, since it's not a field in the model.
I also can't do send("phone=", value), because there's no such method in the controller (results in NoMethodError: undefined method 'phone_number_mobile=' for #<UsersController:)
So - how do set the value for phone to the newly updated object #user, either by the #user.custom_attrs or the UserConcern?

There is a simpler way.
app/models/user.rb
...
attr_accessor :phone
...
You can then access user.phone

Related

confirmation token Automatically generated NIL

I have an issue with an automatically generated token. In a model, I generate the token automatically using:
class User < ApplicationRecord
before_create :generate_confirm_token
def generate_confirm_token
self.confirm_token = generate_token
end
def generate_token
loop do
token = SecureRandom.hex(10)
break token unless User.where(confirm_token: token).exists?
end
end
After creating of user, the token is generated correctly, but the issue is in a controller:
class Companies::StudentsController < ApplicationController
def create
#company = Company.find(params[:company_id])
#student = #company.students.create(student_params)
raise #student.inspect
if #student.save
StudentMailer.with(student: #student).welcome_email.deliver_now
redirect_to company_students_path
else
render :new
end
end
student contains confirm_token BUT in params the confirm token is empty.
I need the token in params because in the mailer I use Find_by(params[:confirm_token]).
Here is how I use a confirm_token in my view. I assume I need the confirm_token in params so I have to have it in a view also:
<%= f.hidden_field :confirm_token %>
The process which is described above is OK.
The issue was in mailer.
student should be in mailer created like this:
#student = params[:student]
but I did it like this:
#student = Student.find_by(confirm_token: :confirm_token)
Which is not correct according to the mailer documentation:
Any key value pair passed to with just becomes the params for the
mailer action. So with(user: #user, account: #user.account) makes
params[:user] and params[:account] available in the mailer action.
Just like controllers have params.

i'm trying to pass json data to rails controller using post method in rest client

Here i'm trying to save json data to sqlite database using rails controller, but i'm not getting json data to controller parameters
In a specific controller I have the below list of params:
Parameters: {"person"=>"{\"name\":\"akhil\",\"profession\":\"it\",\"address\":\"hyderabad\",\"mobilenum\":67588}"}
Controller
def createPerson
puts "parameters are : "+params[:person].to_s
user_params = ActiveSupport::JSON.decode(params[:person])
puts "parameters name:"+user_params[:name].to_s
#person = Person.new(name: user_params[:name], profession:
user_params[:profession], address: user_params[:address], mobilenum:
user_params[:mobilenum])
#person.save
end
It is showing below error
(no implicit conversion of nil into String)
I'm getting the nil value in user_params[:name].to_s
Could you please help me to solve this
Seems like all you need to do is to create a new Person record after submitting a form. Well, probably you would want to use strong params and make a little refactor, so your controller will look something like this:
class PersonsController < ApplicationController
# you can name your action simply `create`, so you can use resource routing
def create
# most probably you don't need to make person an instance variable
person = Person.new(person_params)
# and here it is a good practice to check if you really saved your person
if person.save
# do something to tell user that the record is saved, e.g.
flash[:success] = 'person has been saved'
else
# show user why your person record is not saved, e.g.
flash[:error] = "person cannot be saved: #{person.errors.full_messages.to_sentence}"
end
end
private
# and here is the method for your permissible parameters
def person_params
params.require(:person).permit(:name, :profession, :address, :mobilenum)
end
end

Rails 5 - set field value when empty

In my app I want to add a value to a field if it is empty when the record gets created. It should take the name of the file ( attached to the record.
I tried adding below code to the controller, yet that doesn't do it. How can/should these kind of action be done in Rails 5?
def create
#document = Document.new(document_params)
if #document.update(document_params)
unless #document.name.present?
#document.name == #document.file_file_name
end
redirect_to #document
else
render 'new'
end
end
Use self.attribute
Add callback to model before_save :set_field_name and added a method:
def set_field_name
unless self.name.present?
self.name = self.file_file_name
end
end

Rails ParameterMissing error on create action

When I try to create a user, Rails returns a ParameterMissing error:
ActionController::ParameterMissing in UserController#create
param is missing or the value is empty: user
My Controller
class UserController < ApplicationController
def create
#user = User.new(user_params)
render json: #user
end
private
def user_params
params.require(:user).permit(:fame, :lame, :mobile)
end
end
My User Model
class User < ActiveRecord::Base
self.table_name = "user"
end
What am I doing wrong?
Check your logs for the params that are being sent to your controller. Most likely, the params hash being sent by your view doesn't include the :user, key. To fix, you'll need to make sure your form_for is properly namespaced with a User object:
form_for #user do |f|
# ...
end
You can also use the as key to explicitly set the :user key in your params.
form_for #object, as: :user, method: :post do |f|
# ...
end
Update
Since the questioner was using postman to send data, the data sent to the server should be properly formatted like so:
user[firstName]
Thanks #Fabio and #Anthony
When you asked about the form, I actually realized that the parameter I sending with postman was actually incorrect as they should be like
user[firstName]
Updated
It actually deepns upon you how you send the params.
I send as
user[firstname] So I get like params[:user][:firstName]
If I send like firstname So this will be params[:firstName]

Rails4 - Edit parameters of an Object before remotely saving it in the database

Beginner with some dev experience here.
I have an app with multiple models and I have managed to work everything out but i am stuck here.
I have a model, called CartEntries
class CartEntry < ActiveRecord::Base
acts_as_paranoid
belongs_to :cart
belongs_to :sign
With a create method in the Cart Entry controller
def create
#entry = #cart.entries.create(entry_params)
if #entry.save
flash[:notice] = translate 'flash.notice'
else
flash[:error] = translate 'flash.error'
end
support_ajax_flashes!
respond_to do |format|
format.html # renders view
format.json { render json: #entry }
end
end
And a Model Sign with static signs inputed in the database and no create method.
class Sign < ActiveRecord::Base
has_many :cart_entries
accepts_nested_attributes_for :cart_entries
And from a Sign's view I initialize a new instance of a CartEntry and succsessfuly create a new Cart Entry after clicking the link, generating a notification.
<% #entry = CartEntry.new(sign: #sign)%>
<%= link_to t('.add_to_cart'), user_cart_entries_path(:entry => #entry.attributes),method: :post, remote: true, "data-type" => :json%>
The Cart Entry has another field called Count with a default value of 1. Im looking for a way for the user to input this number in a text field and when creating the Cart Entry , pass the Count the user inputed instead of the default 1.
What ever I try passes the default value.
While
<% #entry = CartEntry.new(sign: #sign, count: 5)%>
Does the trick properly, and passes 5 as the value , but I want the user to input this number since its clearly a variable.
While I understand that
<% #entry = CartEntry.new(sign: #sign)%>
Initializes the entry object on page load and that i must move it, I'm asking you kind people, where?
UPDATE
Entry Params:
private
def entry_params
params.require(:entry).permit(:sign_id, :count)
end
Answering in reverse order from your question:
Initializing the new CartEntry object should probably be in the new action of your controller. Rails controllers often have both new and create, new being tied to rendering the form to receive input and create being the action tied to the 'Submit' button. Your new action is often just something like:
def new
#entry = CartEntry.new(sign: #sign)
end
Your view to prompt the user for data should be named new.html.erb and have the form in it.
For getting the data from the form to your create method, you are half way there I think. If you moved the example you gave:
<% #entry = CartEntry.new(sign: #sign, count: 5)%>
to the create action in the controller, it would be
#entry = CartEntry.new(sign: #sign, count: params[:count])
#entry.save
Remember 'params' is just a hash that contains the form input data.
Hope that helps!

Resources