Passing current user parameters into nested model - ruby-on-rails

I am trying to pass through a devise user id from my Agent model (current_agent.id) into my Nested AgentActivity model whenever I update the parameters on my Submission model. How would I go about achieving this?
Currently my code on Submission controller (doesn't throw an error but doesn't do anything):
#submission.agent_activities.first.agent_id = current_agent.id
respond_to do |format|
if #submission.update(submission_params)
format.html { redirect_to #submission, notice: 'Submission was successfully updated.' }
format.json { render :show, status: :ok, location: #submission }
else
format.html { render :edit }
format.json { render json: #submission.errors, status: :unprocessable_entity }
end
end

Yes, you're just assigning agent_id, but don't saving it. Should be:
#submission.agent_activities.first.update(agent_id: current_agent.id)
And this line should go after if #submission.update(submission_params)

Related

change behaviour of Create if record with same attribute exists

I'm building an app like reddit where you add a Submission to a specific user page. Submission has a few attribute including an attribute called url.
I want to check when adding a new submission if already a submission with that same url exists for that specific page, and if it exist, vote for it instead of creating it as a new submission. If not, just add it as a new submission. I'm using the act_as_votable gem here.
Here is the create method:
def create
#user = User.friendly.find(params[:user_id])
#submission = #user.submissions.new(submission_params)
#submission.member_id = current_user.id
#submission.creator_id = #user.id
#submission.is_viewed = false
#submission.get_thumb_and_title_by_url(#submission.url)
respond_to do |format|
if #submission.save
format.html { redirect_to #user, notice: 'Submission was
successfully created.' }
format.json { render :show, status: :created, location: #submission }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
you should take a look at https://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_create_by and https://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_initialize_by
Now on your code we can make changes like
def create
#user = User.friendly.find(params[:user_id])
#submission = #user.submissions.find_or_initialize_by(submission_params)
if #submission.id.present?
# What to do if the record exists
else
# if its a new record
#submission.member_id = current_user.id
#submission.creator_id = #user.id
#submission.is_viewed = false
#submission.get_thumb_and_title_by_url(#submission.url)
end
respond_to do |format|
if #submission.save
format.html { redirect_to #user, notice: 'Submission was
successfully created.' }
format.json { render :show, status: :created, location: #submission }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I hope that this can put you on the right track
Happy Coding

Rails: How to update multiple models together, with proper rollback (kind of manual nested attributes)

I (for various reasons) have decided not to use nested_attributes. Here is my current controller:
def update
# Update snippet
#snippet.update(snippet_params)
# Update hotspot
#snippet.hotspot.update(hotspot_params)
# Update text
#snippet.text.update(medium_params_with(:text))
# Update audio
if params[:audio] {
#snippet.audio.destroy
#snippet.media << Audio.new(medium_params_with(:audio))
}
respond_to do |format|
if success = true #fix this up
format.html { redirect_to #project, notice: 'Snippet was successfully updated.' }
format.json { render :show, status: :ok, location: #snippet }
else
format.html { redirect_to #project, warning: 'Highlight was not updated.' }
format.json { render json: #snippet.errors, status: :unprocessable_entity }
end
end
end
This is more or less OK if nothing goes wrong.
How do I wrap this into something like:
try {
update everything
} else {
undo any changes I made while trying to update everything
}
if success {
etc
} else {
etc
}
If what you are changing are ActiveRecord models using a SQL database then http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html might provide exactly what you're looking for.
Following #Jonah's answer, I wrapped the DB changes in ActiveRecord::Base.transaction:
def update
success = ActiveRecord::Base.transaction do
# Update snippet
#snippet.update(snippet_params)
# Update text
#snippet.text.update(medium_params_with(:text))
# Update audio
if params[:audio]
#snippet.audio.destroy
#snippet.media << Audio.new(medium_params_with(:audio))
end
end
respond_to do |format|
if success
format.html { redirect_to #project, notice: 'Snippet was successfully updated.' }
format.json { render :show, status: :ok, location: #snippet }
else
format.html { redirect_to #project, warning: 'Highlight was not updated.' }
format.json { render json: #snippet.errors, status: :unprocessable_entity }
end
end
end

rails - URL doesn't match with the view

I have something strange in my rails app, I try to redirect the user to a specific page if a form is wrong formatted. It works but the URL does not match to the view.
I use files generated by rails g scaffold User. I added specific condition in model file to check user input to see if the form is well formatted or not and if not, it redirect him to the connection view.
I redirect him between 2 different controllers
So i turned this (app/controller/users_controller.rb):
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to root_path, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
into this:
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to root_path, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :template => 'pages/connection' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I tried and i'm well redirected to pages/connection.rb but the url in my browser is : http://url:8080/users and not http://url:8080/connection. So if i refresh, it leave pages/connection.rb to users/.
Also, error messages from model/user.rb aren't displayed.
what's wrong in my code ?
You are rendering the template pages/connection, you are not redirecting the user to the other controller.
format.html { render :template => 'pages/connection' }
Render and redirect are not the same

Passing an argument on request.referrer

I'm building a site where a link to fill a new form can be clicked from an Event show page
<%= link_to 'Be a Contestant', new_form_path(:event_id => #event.id)%>
This creates a link like
http://localhost:3000/forms/new?event_id=2
Now if the form is filled with an error, when submitted, it returns an error
Couldn't find Event with 'id'=""
So I decided to use the request.referrer to redirect back to the previous page but it doesn't list the errors as use this method
def create
#form = Form.new(form_params)
respond_to do |format|
if #form.save
format.html { redirect_to #form, notice: 'Form was successfully created.' }
format.json { render :show, status: :created, location: #form }
else
format.html { redirect_to request.referrer }
format.json { render json: #form.errors, status: :unprocessable_entity }
end
end
end
I also tried this but to no avail.
def create
#form = Form.new(form_params)
respond_to do |format|
if #form.save
format.html { redirect_to #form, notice: 'Form was successfully created.' }
format.json { render :show, status: :created, location: #form }
else
format.html { redirect_to new_form_path(:event_id => request.referrer.params[:event_id]) }
format.json { render json: #form.errors, status: :unprocessable_entity }
end
end
end
What you probably really need to do is to add a hidden field event_id to the form because I'm betting that event_id doesn't get propagated from the #new to the #create action.
See here for more information on hidden_field_tag
You usually just render the edit view when there was an error in create:
def create
#form = Form.new(form_params)
respond_to do |format|
if #form.save
format.html { redirect_to #form, notice: 'Form was successfully created.' }
format.json { render :show, status: :created, location: #form }
else
format.html { render :edit, alert: 'Error creating ...' }
format.json { render json: #form.errors, status: :unprocessable_entity }
end
end
end

Rails - ActionController::Parameters include controller value with form values

I have a session variable (user_id) that I'd like to include as a foreign key on a record the user is inserting. I have the form values all coming through the form submit to my controller's entity.update(params) method without a problem using the default params definition. That code looks like
def brand_params
#brand_params = params.require(:brand).permit(:name, :brand_type, :profile_id)
end
The update method looks like
if #brand.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.' }
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
Now I'd like to append the :profile_id session variable to the #brand_params and following other threads here, I've tried a setter method:
def set_brand_params(key, val)
if #brand_params != nil
#brand_params[key] = val
end
end
However, calling this, #brand_params is always nil. Trying to directly add to the brand_params hash doesn't work because it's a better method. If there's a better way to meet this (I'd assume common) use case, I'm all ears! Otherwise, I'd like to know why the var is always nil though in this context, at least the brand_params method sees it as defined and with value. I got this solution in Adding a value to ActionController::Parameters on the server side
Here is the update method as requested:
def update
puts "update"
set_brand_params("profile_id", session[:prof])
respond_to do |format|
if #brand.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.' }
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end
I'm not agree with merge your data with the params. Because you must permit only the fields you expect your user update. In this case you don't want the user update profile_id on brands, and that is a security best practice.
Then brand_params must be:
def brand_params
#brand_params = params.require(:brand).permit(:name, :brand_type)
end
Your method update may look by this:
def update
#brand = Brand.find(params[:id])
#brand.assign_attributes(profile_id: session[:prof])
respond_to do |format|
if #barnd.update(brand_params)
format.html { redirect_to #brand, notice: 'Widget was successfully updated.'}
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end
You don't need the method set_brand_params at all.
If this don't do the trick, please publish the entry controller, and I hope we find the issue.
edit: add respond_to.

Resources