Im trying to upload a photo through my Rails app and everything is fine until I click on "update...". Then it throws me an "ActionController::UnknownFormat" error and fails. Here you can find the form I'm using, the update controller and the model I'm referring to.
Form:
<%= form_with(model: current_user, local: true, html: {multipart: true}) do |form| %>
<div class="field">
<%= form.label :profile_pic %>
<%= form.file_field :profile_pic, id: :profile_pic %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Update method:
def update
#user = current_user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
render action: :edit
end
end
end
Error seems to be here:
respond_to do |format|
model:
require 'digest'
class User < ApplicationRecord
mount_uploader :profile_pic, ProfilePicUploader
attr_accessor :password
before_save :encrypt_new_password
after_create :build_profile
has_one :profile
has_many :trips
has_many :comments, through: :trips, source: :comments
has_many :posts, through: :trips, source: :posts
scope :recent_comments, ->{where("comments.created_at > ? AND user_id = ?", [6.months.ago, self.id]).limit(3)}
#friends
has_many :users
validates :email, uniqueness: {case_sensitive: false, message: 'El correo debe ser único'}, length: {in: 6..50, too_short: "debe tener al menos %{count} caracteres"}, format: {multiline: true,with: /^.+#.+$/, message: "formato de correo no valido"}
validates :password, confirmation: true, length: {within: 4..20}, presence: {if: :password_required?}
validates :password_confirmation, presence: true
def self.authenticate(email,password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end
def authenticated?(password)
self.hashed_password == encrypt(password)
end
protected
def encrypt_new_password
return if password.blank?
self.hashed_password = encrypt(password)
end
def password_required?
hashed_password.blank? || password.present?
end
def encrypt(string)
Digest::SHA1.hexdigest(string)
end
def build_profile
Profile.create(user: self, name: self.name, bio:"Im using Tripper!")
end
end
If anyone could tell me please what did I do wrong...
You have used the respond_to block, but you didn't specify the format in which edit action should be rendered.
Try updating the update action as below:
def update
#user = current_user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render 'edit'} # Specify the format in which you are rendering the 'edit' page
format.json { render json: #user.errors } # If required, specify a json format as well
end
end
end
Try to the following by updating the update action
def update
#user = current_user
respond_to do |format|
if #user.update(user_params)
flash[:notice] = 'User was successfully updated.'
format.html {redirect_to user_path(#user) }
format.json { render :show, status: :ok, location: #user }
else
render action: :edit
end
end
end
Hope to help
Related
i have a rails app. i have strange problem in saving form
this is my ticket model .
class Ticket < ApplicationRecord
belongs_to :user
has_many :ticketissues , inverse_of: :ticket
accepts_nested_attributes_for :ticketissues, :reject_if => lambda { |a| a[:body].blank? }
end
this is ticketisue model
class Ticketissue < ApplicationRecord
belongs_to :user
belongs_to :ticket
validates :body, presence: true
end
this is ticket controller
class TicketsController < ApplicationController
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
# GET /tickets
# GET /tickets.json
def index
#tickets = Ticket.all
end
# GET /tickets/1
# GET /tickets/1.json
def show
end
# GET /tickets/new
def new
#ticket = Ticket.new
end
# GET /tickets/1/edit
def edit
end
# POST /tickets
# POST /tickets.json
def create
#ticket = Ticket.new(ticket_params)
#ticket.user_id = current_user.id
#ticket.ticketissues.build
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render :show, status: :created, location: #ticket }
else
format.html { render :new }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tickets/1
# PATCH/PUT /tickets/1.json
def update
respond_to do |format|
if #ticket.update(ticket_params)
format.html { redirect_to #ticket, notice: 'Ticket was successfully updated.' }
format.json { render :show, status: :ok, location: #ticket }
else
format.html { render :edit }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tickets/1
# DELETE /tickets/1.json
def destroy
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ticket
#ticket = Ticket.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ticket_params
params.require(:ticket).permit(:subject, :subsubject, :user_id, ticketissues_attributes: [
:body, :id, :_destroy] )
#params.require(:ticket).permit!
end
end
and my view is like this
<%= f.input :subject , collection: [ "تغییر اطلاعات کسب و کار",
"تغییر اطلاعات یک کوپن",
"سایر موارد"] %>
<%= f.input :subsubject %>
<!-- <%= f.association :user %> -->
</div>
<%= f.simple_fields_for :ticketissue do |p| %>
<%= p.input :body %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
but when i want to create a ticket , form will not save to database
and i get this error:
Started POST "/tickets" for 127.0.0.1 at 2017-04-11 23:52:33 +0430
Processing by TicketsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fsl6nTe0PjmBKpeuh16BRFlYOw0MB93LEYDVEAl6TtT/uu/LwGTA0P2q0bRxIxBUqHqZINXHntrZLt7MuCG84Q==", "ticket"=>{"subject"=>"تغییر اطلاعات کسب و کار", "subsubject"=>"lk", "ticketissue"=>{"body"=>"lkjkjkjkjkkjkj"}}, "commit"=>"Create Ticket"}
Unpermitted parameter: ticketissue
but when i use console and this command:
Ticket.create(subject: 'test' , subsubject: 'ticket test' , ticketissues_attributes: [{body: "[some thing" }] )
every things work fines and all data save.
tanks for read and help.
You must use the plural here
= f.simple_fields_for :ticketissues do |p|
Error: Unpermitted parameter: properties
I'm whitelisting the properties{} in the request_controller.rb
This usually works but not this time.
I'm not been able to save some of the data entered in a form. The 3 fields that are not saving are coming from a dynamic form "request_type". I followed Rails Cast episode 403 for this solution, which I have working well in another project but not in this one.
Source: http://railscasts.com/episodes/403-dynamic-forms
Sorry if this is a duplicate question, but I've looked at several other questions and I can't pin-point what I'm doing wrong here
I've researched several questions here, but I'm still not able to get it to work:
Rails 4 Nested Attributes Unpermitted Parameters
Nested attributes - Unpermitted parameters Rails 4
I'm omitting some stuff to make it easier to read the code. Please ask me if you need to see more.
Here's the log:
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8EASewOIxY58b+SU+dxd2YAfpjt38IdwNSju69RPwl/OKfx3AfmvLav79igj8CqPbDwi0eJAwojRbtm+C9F6wg==", "request"=>{"name"=>"asdasddaa", "due_date(1i)"=>"2016", "due_date(2i)"=>"9", "due_date(3i)"=>"15", "user_id"=>"1", "project_id"=>"1", "request_type_id"=>"2", "properties"=>{"Name and last name"=>"asdasd", "Mobile"=>"asdada", "Office tel."=>"asdadas"}}, "commit"=>"Create Request"}
Unpermitted parameter: properties
Update
If I change the request_params to this:
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id, properties:{} ).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
end
See:
properties:{}
I get this Error:
Unpermitted parameters: Name and last name, Mobile, Office tel.
request_controller.rb
def new
#request = Request.new
#request_type = RequestType.find(params[:request_type_id])
#project = #request_type.project.id
end
def create
#request = Request.new(request_params)
respond_to do |format|
if #request.save
format.html { redirect_to #request, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id, :properties).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
end
request_types_controller.rb
def new
#request_type = RequestType.new
#project = Project.find(params[:project])
end
def create
#request_type = RequestType.new(request_type_params)
respond_to do |format|
if #request_type.save
format.html { redirect_to #request_type, notice: 'Request type was successfully created.' }
format.json { render :show, status: :created, location: #request_type }
else
format.html { render :new }
format.json { render json: #request_type.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #request_type.update(request_type_params)
format.html { redirect_to #request_type, notice: 'Request type was successfully updated.' }
format.json { render :show, status: :ok, location: #request_type }
else
format.html { render :edit }
format.json { render json: #request_type.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request_type
#request_type = RequestType.find(params[:id])
end
def request_type_params
params.require(:request_type).permit(:name, :project_id, properties:{}, fields_attributes: [:name, :field_type, :required, :id, :_destroy])
# params.require(:product_type).permit(:name, :product_type_id)
end
models/request.rb
class Request < ApplicationRecord
belongs_to :group
belongs_to :user
belongs_to :project
belongs_to :request_type
serialize :properties, Hash
end
models/request_type.rb
class RequestType < ApplicationRecord
belongs_to :project
has_many :fields, class_name: "RequestField"
accepts_nested_attributes_for :fields, allow_destroy: true
has_many :requests
end
models/request_field.rb
class RequestField < ApplicationRecord
belongs_to :request_type
end
views/requests/new.html.erb
<%= form_for #request do |f| %>
<%= f.fields_for :properties, OpenStruct.new(#request.properties) do |builder| %>
<% #request_type.fields.each do |field| %>
<%= render "requests/fields/#{field.field_type}", field: field, f: builder %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit class:"btn btn-primary" %>
</div>
<% end %>
Try removing :properties from your request_params in your request_controller like this:
def request_params
params.require(:request).permit(:name, :due_date, :group_id, :user_id, :project_id, :request_type_id).tap do |whitelisted|
whitelisted[:properties] = params[:request][:properties]
end
EDIT
def request_params
params.require(:request).permit(:id, :name, :due_date, :group_id, :user_id, :project_id, :request_type_id)
params.require(:properties).permit!
end!
I am trying confirmation validation in Rails4 but it does not work correctly.
When i submit the form the message is "Email confirmation can't be blank" instead of "Email doesn't match confirmation"
Here is my code:
enter code here
#model user.rb
class User < ActiveRecord::Base
validates :email, confirmation: true
validates :email_confirmation, presence: true
end
#view
<div class="field">
<%= f.label :email_confirmation %><br>
<%= f.text_field :email_confirmation %>
</div>
#controller
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, 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
You can create a custom validation to check if two fields are the same
validate :check_email
def check_email
errors.add(:email_comfirmation, "Test message") if email == email_confirmation
end
For some reason my validations aren't working correctly. I can submit the form if it's blank, and it gets processed by the controller. Isn't the point of the model to validate the params before it goes to the controller?
My Controller is:
class SubscribersController < ApplicationController
before_action :set_subscriber, only: [:show, :edit, :update]
# GET /subscribers
# GET /subscribers.json
def index
#subscribers = Subscriber.all
end
# GET /subscribers/1
# GET /subscribers/1.json
def show
# This is Wrong, but You Get The Idea
#subscriber = Subscriber.find_by(params[:id])
end
# GET /subscribers/new
def new
#subscriber = Subscriber.new
end
# GET /subscribers/1/edit
def edit
end
# POST /subscribers
# POST /subscribers.json
def create
#subscriber = Subscriber.new(subscriber_params)
respond_to do |format|
if #subscriber.save
format.html { redirect_to :back, notice: 'Thanks For Joining Our Mailing List!' }
format.json { render :back, status: :created, location: #subscriber }
else
format.html { redirect_to :back, notice: 'Error, Invalid Entry, or you are on the List Already!'}
format.json { redirect_to :back, #subscriber.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /subscribers/1
# PATCH/PUT /subscribers/1.json
def update
respond_to do |format|
if #subscriber.update(subscriber_params)
format.html { redirect_to :back, notice: 'Subscriber was successfully updated.' }
format.json { redirect_to :back, status: :ok }
else
format.html { redirect_to :back }
format.json { render json: #subscriber.errors, status: :unprocessable_entity }
end
end
end
# DELETE /subscribers/1
# DELETE /subscribers/1.json
def destroy
if #subscriber = Subscriber.find_by(params[:email])
respond_to do |format|
if #subscriber.destroy
format.html { redirect_to :back, notice: 'Subscriber was successfully destroyed.' }
format.json { head :no_content }
else
format.html { redirect_to :back, notice: 'Something Wrong' }
format.json { render json: #subscriber.errors, status: :unprocessable_entity }
end
end
else
redirect_to :back
flash[:error] = "Couldn't Find That Email Database!"
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_subscriber
#subscriber = Subscriber.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def subscriber_params
params.require(:subscriber).permit(:name, :email)
end
end
and my model is:
class Subscriber < ActiveRecord::Base
before_validation :downcase_email
validates_uniqueness_of :email
validates_format_of :email,:with => Devise::email_regexp
validates_presence_of :name, :message => "Name can't be blank"
validates_presence_of :email, :message => "Need an Email!!", on: :destroy
private
def downcase_email
self.email = self.email.downcase if self.email.present?
end
end
lastly my form:
<div class="five wide column subscriber">
<div class="ui inverted form segment">
<%= simple_form_for(#subscriber) do |f| %>
<%= f.error_notification %>
<h3 class="ui header">Join Our Mailing List</h3>
<div class="two fields">
<div class="field">
<%= f.input :name, placeholder: "Enter Name", required: true, error_html: { id: 'password_error'}%>
</div>
<div class="field">
<%= f.input :email, placeholder: "Enter Email", type: "email", required: true%>
</div>
</div>
<%= f.submit "Join", class: "ui blue submit button" %>
<% end %>
</div>
</div>
Let me know if I need to supply any more information. I hope this is an easy fix, but I'm not sure what I'm doing wrong.
Hello I'm working in a application where you can vote for a product and from the New action of my vote view I get this error:
ActiveModel::MassAssignmentSecurity::Error in VotesController#create
Can't mass-assign protected attributes: product, user
I make a test on rails console and it works. So I don't know what it's going on.
Here are the models:
class Product < ActiveRecord::Base
attr_accessible :title
has_many :votes
has_many :users, :through => :votes
has_attached_file :photo, :styles => { :medium => "300x300" }
before_save { |product| product.title = title.titlecase }
validates :title, presence: true, uniqueness: { case_sensitive: false }
validates :photo, :attachment_presence => true
end
class User < ActiveRecord::Base
has_many :votes
has_many :products, :through => :votes
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
class Vote < ActiveRecord::Base
attr_accessible :product_id, :user_id
belongs_to :product
belongs_to :user
end
Here is the vote controller
class VotesController < ApplicationController
# GET /votes
# GET /votes.json
def index
#votes = Vote.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #votes }
end
end
# GET /votes/1
# GET /votes/1.json
def show
#vote = Vote.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #vote }
end
end
# GET /votes/new
# GET /votes/new.json
def new
#vote = Vote.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #vote }
end
end
# GET /votes/1/edit
def edit
#vote = Vote.find(params[:id])
end
# POST /votes
# POST /votes.json
def create
#vote = Vote.new(params[:vote])
respond_to do |format|
if #vote.save
format.html { redirect_to #vote, notice: 'Vote was successfully created.' }
format.json { render json: #vote, status: :created, location: #vote }
else
format.html { render action: "new" }
format.json { render json: #vote.errors, status: :unprocessable_entity }
end
end
end
# PUT /votes/1
# PUT /votes/1.json
def update
#vote = Vote.find(params[:id])
respond_to do |format|
if #vote.update_attributes(params[:vote])
format.html { redirect_to #vote, notice: 'Vote was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #vote.errors, status: :unprocessable_entity }
end
end
end
# DELETE /votes/1
# DELETE /votes/1.json
def destroy
#vote = Vote.find(params[:id])
#vote.destroy
respond_to do |format|
format.html { redirect_to votes_url }
format.json { head :no_content }
end
end
end
and here is the new vote view
<%= form_for(#vote) do |f| %>
<% if #vote.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#vote.errors.count, "error") %> prohibited this vote from being saved:</h2>
<ul>
<% #vote.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :product %><br />
<%= f.text_field :product %>
</div>
<div class="field">
<%= f.label :user %><br />
<%= f.text_field :user %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Please I really need your help to solve this issues, it was very difficult to find a tutorial with has_many :through that include the complete MVC example, I think my problem is on the view, but I don't know.
Thanks!
That error message tells you everything you need to know if you look closely at it.
ActiveModel::MassAssignmentSecurity::Error in VotesController#create
Can't mass-assign protected attributes: product, user
you may not be familiar with the term "mass-assignment". its the assignment of 1 or more of an objects attributes at the time of creation. i.e. in VotesController#create.
when unprotected, mass-assignment opens you up to hackers assigning values to any and all of an objects attributes in your site's forms wether you meant to give access or not.
thats where attar_accessible comes in. it forces you to be explicit about what attributes of a model your users should have access to. any not passed as symbols into the macro will be protected attributes as in Can't mass-assign protected attributes: product, user.
the scaffolding set attr_accessible :product_id, :user_id when it created your model but it didnt know you were going to assign these with objects rather than id values.
you can fix this one of 2 ways.
change your form so that the hash-like params variable assigns like this
params[vote][product_id]
or change your model like
attr_accessible :product, :user