I have trouble with my image update
My form
= form_for #user, :html => {class: "form form_profile"} do |user|
= user.file_field :avatar
.... other fields
end
and controller update and user_avatar_params action
def update
respond_to do |format|
# binding.pry
if params[:user][:avatar]
if current_user.update(user_avatar_params)
flash[:notice] = 'Updated
format.html { render action: 'edit' }
format.js { render 'success_edit', layout: false }
....
end
def user_avatar_params
params.require(:user).permit(:avatar)
end
my params from console
{"utf8"=>"✓", "_method"=>"patch", "user"=>{"current_password"=>"", "password"=>""}, "action"=>"update", "controller"=>"users", "id"=>"2"}
i use paperclip
What wrong with it?
Try to add html: { multipart: true } code like in the example below.
<%= form_for #user, url: users_path, html: { multipart: true } do |form| %>
<%= form.file_field :avatar %>
<% end %>
Related
hope your having a wonderful day drinking some coffee and responding to some forms.
Problem:
As my title states, I am trying to create 2 forms on one view. I am new to ruby on rails.
My controller functions:
Controller name is border_rotation:
def create
if params[:export_submit]
#border_rotation_export = BorderRotationExport.new(border_rotation_export_params)
respond_to do |format|
if #border_rotation_export.save
flash[:success] = "Export successfully created"
format.html { render :new }
else
flash[:error] = "Export was not created."
end
end
else
#border_rotation_import = BorderRotationImport.new(border_rotation_import_params)
respond_to do |format|
if #border_rotation_import.save
flash[:success] = "Export successfully created"
format.html { render :new }
else
flash[:error] = "Export was not created."
end
end
end
end
def new
#border_rotation_export = BorderRotationExport.new
#border_rotation_import = BorderRotationImport.new
end
private
def border_rotation_export_params
params.require(:border_rotation_export).permit(:exporter_name,:vehicle_color,:rot_num,:current_date,:current_time,:goods_description,:license_num,:entry)
end
def border_rotation_import_params
params.require(:border_rotation_import).permit(:importer_name,:vehicle_color,:rot_num,:current_date,:current_time,:goods_description,:license_num,:entry)
end
My new View form:
It has 2 forms and is enclosed in bootstrap tabs
<%= form_for #border_rotation_export, url: rotation_create_path, method: :post do |f|%>
<lable>Importer Name: </lable><%= f.text_field :importer_name, class: "form-control", placeholder: "Importer Name"%>
<lable>Vehicle Color: </lable><%= f.text_field :vehicle_color, class: "form-control", placeholder: "Vehicle Color"%>
**its fields**
<% end %>
and
<%= form_for #border_rotation_import, url: rotation_create_path, method: :post do |f|%>
<lable>Exporter Name: </lable><%= f.text_field :exporter_name, class: "form-control", placeholder: "Exporter Name"%>
<lable>Vehicle Color: </lable><%= f.text_field :vehicle_color, class: "form-control", placeholder: "Vehicle Color"%>
**its fields**
<% end %>
The error in my new.html.rb
First argument in form cannot contain nil or be empty
Displays this in red highlighted
<%= form_for #border_rotation_export, url: rotation_create_path, method: :post do |f|%>
My guess is that it submits both forms but only has the parameters for one form with the input data. Once I submit, it saves to the database but it gives me the error
**Routes **
get 'rotation/create', to: 'border_rotation#create'
post 'rotation/create', to: 'border_rotation#create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"Cu52CIDgrY0b7Yk6edkd7+RTl5yR4qSEqPPrqWtM0nIQVDvw7eYDF36zduJPLjI+vVNqCfgtLcMDUEkW6qDOdQ==",
"border_rotation_import"=>
{"importer_name"=>"john",
"vehicle_color"=>"red",
"rot_num"=>"11sssfeeea",
"current_date"=>"2021-09-22",
"current_time"=>"09:37",
"goods_description"=>"yogurt",
"license_num"=>"c-11223",
"entry"=>"c1223"},
"import_submit"=>"Submit"}
Thank you in advance
You can setup the controller with a lot less redundancy:
# config/routes.rb
resources :rotations, only: [:new, :create]
class BorderRotationsController < ApplicationController
# GET /rotations/new
def new
populate_forms
end
# POST /rotations
def create
resource = model_class.new(create_params)
set_ivar(resource) # sets #border_rotation_export or #border_rotation_import
if resource.save
flash[:success] = "#{humanized} successfully created"
redirect_to action: :new
else
populate_forms
flash[:error] = "#{humanized} could not be created - please try again."
render :new
end
end
private
# gets the model class via params[:subtype]
def model_class
#model_class ||= begin do
if params[:border_rotation_export].present?
BorderRotationExport
else
BorderRotationImport
end
end
end
def humanized
model_class == BorderRotationExport ? 'Export' : 'Import'
end
def set_ivar(value)
instance_variable_set(
"##{param_key}",
value
)
end
# just sets up the instance variables for the form
def populate_forms
#border_rotation_export ||= BorderRotationExport.new
#border_rotation_import ||= BorderRotationImport.new
end
# border_rotation_export or border_rotation_import
def param_key
model_class.model_name.param_key
end
def create_params
require(param_key).permit(
:exporter_name, :vehicle_color, :rot_num,
:current_date,:current_time, :goods_description,
:license_num, :entry
)
end
And then use partials so that you can resuse the same form:
# app/views/border_rotations/new.html.erb
<%= render partial: 'form',
locals: { border_rotation: #border_rotation_export } %>
<%= render partial: 'form',
locals: { border_rotation: #border_rotation_import } %>
# app/views/border_rotations/new.html.erb
<%= form_with model: border_rotation, url: rotations_path do |f| %>
<div class="field">
<%= f.label :importer_name %>
<%= f.text_field :importer_name, class: "form-control" %>
</div>
<div class="field">
<%= f.label :importer_name %>
<%= f.text_field :importer_name, class: "form-control" %>
</div>
# ...
<% end %>
If the requirements diverge use two separate routes/controllers and inheritance instead of blooming out in tons of new code paths.
In my app there is a list of items which you can upvote. I want to make these votes with AJAX calls.
This is the view:
<ul class="list-groups">
<% #questions.each do |question| %>
<li class="list-group-item">
<%= link_to question.description, question_path(question) %>
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, html: { class: 'form-inline' }) do |f| %>
<%= f.submit 'Up vote', class: "btn btn-default" %>
<%= f.hidden_field :id, :value => question.id %>
<% end %>
</li>
<% end %>
</ul>
And this the method that does it:
class VoteController < ApplicationController
respond_to :json
def vote
question_id = params[:question][:id]
user_id = current_user.id
vote = Vote.where(["question_id = :q", { q: question_id }]).where(["user_id = :u", { u: user_id }])
respond_to do |format|
if vote.nil?
#vote = Vote.new
#vote.question_id = question_id
#vote.user_id = user_id
#vote.save
format.html { render '/home/index' }
format.json { render :json => { :status => 'ok' } }
else
format.html { render '/home/index' }
format.json { render :json => { :status => 'failed', :msg => 'You already voted' } }
end
end
end
end
If I don't include this format.html { render '/home/index' } I am getting this error:
ActionController::UnknownFormat in VoteController#vote
But I don't want to render the page again, I am just loading the pieces of html that will change after the action with jQuery and ajax.
How can I respond only with the json?
Use respond_with instead of respond_to in your controller action.
respond_with do |format|
respond_to at the top of your controller is designed to work with respond_with in your controller action, whereas respond_to in your controller action ignores the respond_to that you've defined at the top of your controller.
Also make sure you are making a remote call, instead of a normall one if you want your request to go through AJAX.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, remote: true, html: { class: 'form-inline' }) do |f| %>
Note the remote: true part that is added as an argument to the form_for helper.
You need to include remote: true in form_for in order to make the call requests AJAX instead of HTML.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), remote: true, method: :post, html: { class: 'form-inline' }) do |f| %>
Check out the Working with JavaScript in Rails documentation for more information.
When I submit the form below the "published" check_box value is not posting.
params3 = {"utf8"=>"✓",
"authenticity_token"=>"i4SbblLJKIwba9yD30sDQCsir28/xdUxQZ90qYTNn0A=",
"story"=>{"name"=>"asdsaddsad", "post"=>"asdasdasdasd",
"user_id"=>"13", "image_id"=>"1", "published"=>"1"}, "commit"=>"Save
Story", "action"=>"create", "controller"=>"stories"}
def create
#story = Story.new(story_params)
respond_to do |format|
if #story.save
format.html { redirect_to #story, notice: 'Story was successfully created.' }
format.json { render action: 'show', status: :created, location: #story }
else
format.html { render action: 'new' }
format.json { render json: #story.errors, status: :unprocessable_entity }
end
end
end
<%= form_for #story do |f| %>
<%= f.text_field :name, placeholder: "Enter Title" %>
<%= f.text_area :post, placeholder: "Enter Story" %>
<br/>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.hidden_field :image_id, value: #image.id %>
<%= f.label "Publish this" %>
<%= f.check_box :published %>
<%= f.submit "Save Story" %>
<% end %>
The data that is being passed to the action is story as seen in the params3 hash. Also, the published check box is being posted. Check boxes by default will pass a 1 or 0 to denote true / false. Rails will update the value accordingly and accept 1 or 0 for the value of a checkbox:
params3 = {"utf8"=>"✓", "authenticity_token"=>"i4SbblLJKIwba9yD30sDQCsir28/xdUxQZ90qYTNn0A=", "**story**"=>{"name"=>"asdsaddsad", "post"=>"asdasdasdasd", "user_id"=>"13", "image_id"=>"1", "published"=>"1"}, "commit"=>"Save Story", "action"=>"create", "controller"=>"stories"}
Therefore your object creation will need to use those params. Since you are using Rails 4, you will need to use strong_parameters which seems that you are. You will need to verify that published is an allowed value in your params hash.
def story_params
params.require(:story).permit(...., :published, ...)
end
In my controller I coded like this
class CompanyUploadRequestsController < ApiController
def index
respond_to do |format|
format.html { render action: "index" }
end
end
def create
puts params
respond_to do |format|
format.html { render action: "index" }
end
end
def new
end
end
and in my view new.html.haml file
- page_title("Upload Company")
%h1 Upload Company
%hr
#upload-form
= simple_form_for(#company_upload, :as => :company_update, :url => company_upload_requests_path(#company_upload), :html => { :class => 'file-style'}) do |f|
= f.error_notification
.form-inputs
= f.input :requestname, :label => false, :id => "request_name_input"
= f.input :file,:as => :file, :label => false, :id => "file_select_input"
.form-actions
!= link_to 'Cancel', company_upload_requests_path, :class => 'btn'
= f.button :submit, 'Upload', :class => 'btn-primary'
In my index.html.haml file I have this
- page_title("Upload Company")
%h1 Company index
= link_to("Upload File", new_company_upload_request_path, :class => "btn btn-primary pull-right")
The problem is when I click upload button its not render to index page from create
Here I got the log like this
Processing by CompanyUploadRequestsController#create as HTML
Parameters: {"utf8"=>"?", "authenticity_token"=>"oygIP62E4GHefhN9OnvB3sKhddIb4CN/izfvF5GQtuI=", "company_update"=>{"requestname"=>""}, "commit"=>"Upload"}
Rendered company_upload_requests/create.html.haml within layouts/application (9.8ms)
How can I render to index action and view index file content.
Use like this.
def index
#company_uploads = ModelName.all
respond_to do |format|
format.html
end
end
No need to render index action in index response.
def create
puts params
respond_to do |format|
format.html { render "index" }
end
end
Change the render in your create method to redirect_to
def create
puts params
respond_to do |format|
format.html { redirect_to action: "index" }
end
end
For more explanation on render vs redirect_to, see this SO Question or this.
I get a ForbiddenAttributesError when I send an update to my Rails 4 controller.
The model is 'Company' and it has a private method in it's controller:
def company_params
params.require(:company).permit( :adress_id,
:name,
:zusatz,
:kontakt,
:strasse,
:adresszusatz,
:plz,
:ort,
:telefon,
:fax,
:natel,
:email,
:alternative_email,
:url,
:anbieter_id,
:eintrittsdatum,
:betrag,
:bemerkungen,
:betrag_gwrj,
:betrag_sgkv,
:rechnungszusatz,
:zusatzfeld_7,
:zusatzfeld_8,
:zusatzfeld_9,
:zusatzfeld_10,
:datum_mutation,
:verzeichnis_id,
:industry_ids => []#,
#:latitude,
#:longitude
)
end
BetterErrors shows me these Request parameters:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"0rDHB7BNuHikL3/Fktdaj6BFFDinpUwPdpy+12HdMw4=", "company"=>{"adress_id"=>"", "name"=>"AGIP Tankstelle Rapperswil", "zusatz"=>"", "kontakt"=>"Eni Suisse S.A.", "strasse"=>"Zürcherstrasse 92", "adresszusatz"=>"", "plz"=>"8640", "ort"=>"Rapperswil", "telefon"=>"", "fax"=>"", "natel"=>"", "email"=>"", "url"=>"", "anbieter_id"=>"", "eintrittsdatum"=>"", "betrag"=>"", "bemerkungen"=>"", "betrag_gwrj"=>"", "betrag_sgkv"=>"", "rechnungszusatz"=>"", "zusatzfeld_7"=>"test", "zusatzfeld_8"=>"", "zusatzfeld_9"=>"", "zusatzfeld_10"=>"", "datum_mutation"=>"", "verzeichnis_id"=>"HR & Stadt", "alternative_email"=>""}, "commit"=>"Speichern", "action"=>"update", "controller"=>"companies", "id"=>"375"}
The form looks like this:
...
<%= form_for #company, url: {action: "update"}, html: {class: "form-horizontal"} do |f| %>
<div class="col-md-6">
<div class="form-group">
<%= f.label :adress_id %>
<%= f.text_field :adress_id %>
</div>
...
<%= f.submit "Speichern" %>
</div>
<% end %>
And this is the Update Method in the controller:
def update
#company = Company.find(params[:id])
if #company.update_attributes(params[:company])
redirect_to(#company)
else
render :edit
end
end
If I use the "company" hash in the rails console and create a company via Company.create [hash], it works fine. Any idea why Rails is throwing this error at me?
Be sure than in your controller you're using company_params in update_attributes:
def update
#company = Company.find(params[:id])
respond_to do |format|
# Here use company_params and not params[:company]
if #company.update_attributes(company_params)
format.html { redirect_to #company, notice: 'company updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end