Rails ActiveModel::ForbiddenAttributesError - ruby-on-rails

rarils 4.0.0
I'm trying to post a comments but I have an error:
ActiveModel::ForbiddenAttributesError in CommentsController#create
ActiveModel::ForbiddenAttributesError
def create
#comment = #article.comments.new(params[:comment]) #error point highlight this line
Parameters
{"utf8"=>"✓",
"authenticity_token"=>"zSq3KpEbucFQLa6XStEJ/I0+CpKPLFYcU/WGIdneeMg=",
"comment"=>{"name"=>"g12345",
"email"=>"g12345#12345.com",
"body"=>"hello hello"},
"commit"=>"Add",
"article_id"=>"5"}
my comments/new.html.erb
<%= form_for([#article, #article.comments.new], remote: true) do |f| %>
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit 'Add' %>
</div>
<% end %>

Rails 4 uses strong parameters by default. Do you have something like:
params.require(:some_param).permit(...)
or
params.permit(:list, :of, :allowed, :params)
in your CommentsController?
It would look something like this:
class CommentsController < ApplicationController
def create
#comment = #article.comments.new(comment_params) #error point highlight this line
end
private
def comment_params
params.require(:comment).permit(:name, :email, :body)
end
end

Related

Type mismatch on association, f.select rails

I have a problem in my form, i want to create an entry in my "members" table, each member are connected to a "year" but I keep getting mismatches on the selection of the year.
This is my form:
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
And here are the models:
class Member < ApplicationRecord
belongs_to :year
mount_uploader :image, ImageUploader
end
class Year < ApplicationRecord
has_many :members, dependent: :destroy
end
When I try to submit I get the following error:
Year(#70050157849460) expected, got "1" which is an instance of String(#9412380)
Where did I go wrong?
EDIT:
Here is the code for the controller
class MembersController < ApplicationController
def home
#members = Member.all
end
def new
#member = Member.new
#years = Year.all
end
def create
#member = Member.new(member_params)
if #member.save
flash[:success] = "Member Created"
redirect_to root_path
else
render 'form'
end
end
private
def member_params
params.require(:member).permit(:name,:nick,:position,:image,:year)
end
end
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year_id, options_for_select(#years.all.map{|y| [y.year,y.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
or
<div class="field">
<%= f.label :name %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :nickname %><br>
<%= f.text_area :nickname %>
</div>
<div class="field">
<%= f.label :year %>
<%= f.select :year, options_for_select(#years.all.map{|y| [y.year,y]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
This second I did not check but first will work you need to say year_id because when you did map on collection you set id as parameter that is being passed
but on form select you basically told form to expect active record object.

Showing :name from signup form in profiles form using Devise in rails app

I need my App to be able to display :name from the sign up form in the profiles/new _form is that possible? and how?
When my User sign up for an account via Devise they sign up by inserting :name, emailand password. Like seen in the code below:
<div class="row img-back">
<div class="col-md-6 col-md-offset-3 text-center">
<div class="well sign-up-form">
<h2>Ný skráning</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field form-group">
<%= f.label :Nafn_fyrirtækis_stofnunar %><br />
<%= f.text_field :name, autofocus: true, class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :tölvu_póstfang %><br />
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :Lykilorð %>
<% if #minimum_password_length %>
<em>(Minnst <%= #minimum_password_length %> stafir )</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :Staðfesting_lykilorðs %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control' %>
</div>
<div class="actions">
<%= f.submit "Ný skrá", class: 'btn btn-success' %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>
After Sign up the user is directed to the views/profiles/new.html.erb with this method in registrations_controller.rb
def after_sign_up_path_for(resource)
new_user_profile_path(current_user)
end
And in the views/profiles/new.html.erb the user fills in a _form.html.erb partial to finish its profile and register all the information the app needs to work for the user.
this is the _form.html.erb
%= form_for #profile, url: user_profile_path, :html => { :multipart => true } do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :avatar %>
<%= f.file_field :avatar, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :staff %>
<%= f.number_field :staff, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :building_size %>
<%= f.number_field :building_size, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :address %>
<%= f.text_field :address, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :postalcode %>
<%= f.text_field :postalcode, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :website%>
<%= f.text_field :website, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :contact_person %>
<%= f.text_field :contact_person, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :contact_email %>
<%= f.email_field :contact_email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :phone_number %>
<%= f.text_field :phone_number, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :buisness_type %>
<%= f.select :buisness_type,['Þjónusta', 'Ráðgjöf', 'Verlsun', 'Stofnun', 'Annað'], class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.submit "Update Profile", class: 'btn btn-primary' %>
</div>
<% end %>
My profile.rb belongs_to :userand my user.rb model has_one :profile
EDIT according to jsw324 answer
Here is the profiles_controller.rb
class ProfilesController < ApplicationController
before_action :authenticate_user!
#before_action :only_current_user
def new
#form where a user can fill put their pwn profile.
#user = User.find(params[:user_id]) # Finnur hver er userinn sem er loggaður inn, reaching in to the url and grabbs user.
#profile = Profile.new
#profile.name = current_user.name
end
def show
#user = User.find(params[:user_id])
##profile = #user.profile
#profile.name = current_user.name
end
def create
#user = User.find(params[:user_id])
#profile = #user.build_profile(profile_params)
#Lecture 159 User show action next :))))
if #profile.save
flash[:success] = "Profile updated"
redirect_to user_path(params[:user_id]) #fer á user/show.html.erb
else
render action: :new
end
end
def edit
#user = User.find(params[:user_id])
#profile = #user.profile
end
def update
#user = User.find(params[:user_id])
#profile = #user.profile
if #profile.update_attributes(profile_params)
flash[:success] = "Profile Updated!"
redirect_to user_path(params[:user_id])
else
render action :edit
end
end
private
def profile_params
params.require(:profile).permit(:name, :staff, :address, :postalcode, :website, :contact_person, :contact_email, :phone_number, :buisness_type, :description, :building_size, :avatar)
end
def only_current_user
#user = User.find(params[:user_id])
redirect_to(root_url) unless #user == current_user
end
And I edited this line in the views/profiles/_form.html.erb
<%= form_for #profile, url: user_profile_path, :html => { :multipart => true } do |f| %>
<div class="row">
<div class="container">
<div class="col-md-6">
<div class="form-group">
<%= f.label :Name %>
<%= f.name %>
</div>
Now I get this Error: undefined methodname' for #`
Ahh. You need to handle that in the controller. Something like #profiles.name = current_user.name.
I'm not sure I understand but to display the name you can just use <%= current_user.name %> wherever you need it.

undefined method ` ' for #<ContactsController:0x007fc3a821e300>

I have been following the tutorial (http://guides.rubyonrails.org/getting_started.html ) to create my own web app for create a contact manager.
When I want to create a new contact, I have code in my contacts_controller
class ContactsController < ApplicationController
def show
#contact = Contact.find(params[:id])
end
def new
end
def create
#contact = Contact.new(contact_params)
#contact.save
redirect_to #contact
end
private
def contact_params
params.require(:contact).permit(:firstname, :lastname, :email, :phonenumber, :notes)
end
end
In the view I have
<h1>New Contact</h1>
<%= form_for :contact, url: contacts_path do |f| %>
<p>
<%= f.label :firstname %><br>
<%= f.text_field :firstname %>
</p>
<p>
<%= f.label :lastname %><br>
<%= f.text_field :lastname %>
</p>
<p>
<%= f.label :email %><br>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :phonenumber %><br>
<%= f.text_field :phonenumber %>
</p>
<p>
<%= f.label :notes %><br>
<%= f.text_area :notes %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
In routes.rb
Rails.application.routes.draw do
get 'welcome/index'
root 'welcome#index'
resources :contacts
end
However, when I submit the form, I got this error message.
I think I followed the tutorial correctly and have the new method in my class. This seems weird to me and I have no idea to start debugging this app.

Rails 4 Integer number field returns string

When I enter something into a number_field and post the form to the controller, Rails can't save because i have a numericality validation:
validates :rating, numericality: { greater_than: 0, less_than: 6 }
I debugged the controller by this piece of code:
raise "It exploded into pieces!" unless #comment.save
The exception I used for debugging said that my :rating was a string instead of an integer. Before this, i rendered the json errors for #comment and that said that :rating was not a number.
These are very useful to spot the problem, but I can't find any solutions to fix the problem. I checked the database schema and it says that :rating should be an integer, as in:
t.integer "rating"
I don't know what to do at this point. Can somebody help me? Thank you in advance.
P.S. I use number_field.
P.P.S.
In my controller:
def ccreate
#comment = Comment.new(params.permit(:rating, :body, :name, :game_id))
raise "It exploded into pieces!" unless #comment.save
end
In my view:
<% if #comments.count < 10 %>
<%= form_for(comment_path) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
It's a strong params thing. Permit :comments, then the attributes
params.require(:comments).permit(:rating, :body, :name, :game_id)
and, use form_for #comment, not comment_path
I think you need to setup the form properly, I think the validation will work fine if the form posts as it should:
comments_controller.rb
def new
#comment = Comment.new
end
def create
#comment = Comment.new(comment_params)
raise "It exploded into pieces!" unless #comment.save
end
private
def comment_params
params.require(:comment).permit(:rating, :body, :name, :game_id)
end
There we are changing the strong params to require the new comment key in params (which will be the result of the second change to the view below). I also moved this into a private function to clean this up.
So then in your view:
<% if #comments.count < 10 %>
<%= form_for(#comment) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
This uses the form_for tag with the model instance which should, I think, solve this issue.
try this in the comment_controller.rb
#rating = params[:comment][:rating].to_i
to make every input of the ratings to be converted as integer

Submit button points to wrong action

I am building a form to work with a non activerecord model. I have two problems..
When I point to keyword/id/edit my form's submit button says 'create keyword', and pressing that submit button takes me to the create method on my keyword controller. It should be taking me to the update action.
I would also like to send an attribute called 'id' to my update action. I'm not sure how to do this. Like I said this isn't an activerecord model.
/views/keywords/_form.html.erb
<%= form_for(#keyword) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :keyword %><br />
<%= f.text_field :keyword %>
</div>
<div class="field">
<%= f.label :message1 %><br />
<%= f.text_area :message1 %>
</div>
<div class="field">
<%= f.label :message2 %><br />
<%= f.text_area :message2 %>
</div>
<div class="field">
<%= f.label :start_time %><br />
<%= f.text_area :start_time %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
/controller/keywords_controller.rb >> edit action
def edit
result = Keyword.find(params[:id])
result = result.to_array(:get_response, :return, :data, :item)
result = result.first
#keyword = Keyword.new
#keyword.id = result[:item][0][:value]
#keyword.name = result[:item][1][:value]
#keyword.keyword = result[:item][2][:value]
#keyword.message1 = result[:item][3][:value]
if(result[:item][4][:value] != {:"#xsi:type"=>"xsd:string"})
#keyword.message2 = result[:item][4][:value]
end
#keyword.start_time = result[:item][5][:value]
end
/models/keyword.rb
class Keyword
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?
false
end
attr_accessor :id, :name, :keyword, :message1, :message2, :start_time
def self.get_keywords(cid)
#get data from webservice
end
end
config/routes.rb
SchoolBeacon::Application.routes.draw do
devise_for :users
devise_for :admins
resources :keywords
end
Change your #keyword = Keyword.new line in your edit action to #keyword = Keyword.find(params[:id]) or however you find the keyword. If you are using normal RESTful rails routes, that should do it.
Actually, you can just do form_for(#keyword, :url => keyword_path(#result) and change your result to an ivar(result becomes #result)

Resources