When I try to submit a new status I get the below. I have a registration form that is working fine, not sure what is going on here. Appreciate the help.
def status_params
params.require(:status).permit(:type_id, :user_id)
end
and
def create
#status = Status.new(status_params)
respond_to do |format|
if #status.save
The request
{"utf8"=>"✓",
"authenticity_token"=>"gZPV4FfSm2eb+pGPbAAqI4zA/LHJiAsRkHdJar/aU3G63oBiaLr55zPoRv3K+7EmelN2Nofj/CTZ+qPtoYih5w==",
"type"=>{"user_id"=>"3"},
"type_id"=>"Ocular",
"commit"=>"Create Status"}
My View
<div class="field">
<%= f.label :user_id %><br>
<%= select(:user_id, #user_options) %>
</div>
<div class="field">
<%= f.label :type_id %><br>
<%= select_tag :type_id, options_for_select(mg_types) %>
</div>
Your params are not in status hash. So,
Try this -
def status_params
params.permit(:type_id, type[:user_id])
end
I can see multiple problems here:
The posted parameters are not wrapped in a status hash.
You are posting an attribute hash called type that contains a user_id, which is inconsistent with your whitelisted attributes.
You are also posting an attribute called type_id that contains a String (and not an id).
Posting both type and type_id conflicts because Rails will set these attributes on the Status model and one will probably override the other.
Related
I'm trying to submit a form in ruby on rails that i made, but keep getting de next error.
Ruby on Rails form: param is missing or the value is empty
my form
<%= form_for #test do |f| %>
<div class="field">
<%= f.text_field :first_name %><br>
<%= f.text_field :last_name %><br>
</div>
<div class="actions">
<%= f.submit "Create" %>
</div>
<% end %>
my controller
def new
#test = Test.new
end
def create
#test = Test.new(allow_params)
if #test.save
redirect_to 'test/index'
else
render 'test/new'
end
end
private
def allow_params
params.require(:last_name).permit(:first_name)
end
my routes
resources :test
get 'test/index'
get 'test/new'
get 'test/create'
post '/tests' => 'test#create'
Your attributes are within the testlabel, so here you should go :
def allow_params
params.require(:test).permit(:first_name, :last_name)
end
Look, this is what you form posts when you click submit:
{"utf8"=>"✓","authenticity_token"=>"...", "test"=>"first_name"=>"poldo", "last_name"=>"de poldis"},"commit"=>"Create"}
As you can see first_name and last_name are inside an hash as value of a key called test. Indeed your function allow_params expects something like this
last_name: {first_name: 'poldo'}
as you can see the param (last_name) is missing, because is inside test!
The right way is as Ben answered:
params.require(:test).permit(:first_name, :last_name)
To understand better how strong parameters works I suggest to you to check this page Api doc or even better The latest version ofthe official manual
I've been trying to create a form that would get parameters for multiple models. I have a photo model that belongs to a product model and I want to make it so that when you create a new product you can also upload images that are linked to that product by id.
<%= form_for #product, html:{multipart:true} do |f| %>
<div class="field">
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<%=form_for #photo do |t| %>
<%t.productID = f.id%>
<div class="field">
<%= t.label (:image) %>
<%= t.file_field (:image) %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<%end%>
right now I'm using paperclip for image attachments and the photo model accepts the images as parameters. I've used paperclip before but the product could only have one image connected to it. If I use the form above I get "First argument in form cannot contain nil or be empty" error and it points to where the form_for #photo starts.I have controllers for both with the usual methods of new, create, update, etc. I've routed resources to both product and photos but I'm still pretty new to rails and don't fully understand how this stuff works.
I think what you're trying to do is a good application for nested forms using the fields_for helper.
First, you'll need to ensure that your product model and photo model have the right associations (A product probably has_many photos, and a photo belongs to a product, right?). Then you'll make sure the product class 'accepts nested attributes for photo's which allows you to add attributes to the photos model from a products form.
in products.rb
class Product
has_many :photos
accepts_nested_attributes_for :photos
end
and in photo.rb
class Photo
belongs_to :product
end
Then you'll want to make sure any attributes you need for the photo are white-listed in your product params.
in products_controller.rb
private
def product_params
params.require(product).permit(:first_product_attribute, :second_produtc_attribute, photo_attributes: [:image])
end
Last, you'll create the form using the special helper fields_for
in your view
<%= form_for #product, html:{multipart:true} do |f| %>
<div class="field">
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<%= f.fields_for :photo do |t| %>
<div>
<%= t.label :image %>
<%= t.file_field :image, :multiple => true %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<%end%>
You'll also need to make sure you're actually creating new photo objects in your product's create action:
in products_controller.rb
def create
#product = Product.new(product_params)
if #product.save!
params[:photo]['image'].each do |img|
#photo = #product.photos.create!(:image => img)
end
flash[:success] = 'product saved!'
redirect_to #product
end
end
Some of this is based on my experience doing the same thing but with Carrierwave instead of Paperclip so your specific implementation might be a little different.
I dont think this is a proper method <%t.productID = f.id%>. Maybe try <% t.text_field :productID, value = f.id, type = hidden %> or something along those lines?
heres some docs for the form helper so you know what to put after t.abcd
http://apidock.com/rails/v3.2.3/ActionView/Helpers/FormHelper/form_for
You're getting the
"First argument in form cannot contain nil or be empty"
..error because #photo is nil, you need to set it in your controller #photo = Photo.new.
Also, form tags inside form tags are invalid HTML.
https://www.w3.org/TR/html5/forms.html#the-form-element
Forms
Content model: Flow content, but with no form element
descendants.
You want to use f.fields_for instead. Learn how to use it here here
I have controllers for both with the usual methods of new, create,
update, etc.
You only ever hit one controller and action when you go to a path, say /photos will only hit the photos controller (as configured in your routes.rb). This I think is where you're messing up the #photo variable. Set both in the same controller in order for the view to be able to see both variables.
I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
I'm totally new to Rails and I'm playing with it. Now I'm trying to understand the strong parameter feature introduced in Rails 4. Below is my code:
class PostsController < ApplicationController
def index
end
def show
end
def create
p = Post.new(create_post_params)
p.save
redirect_to p
end
def new
end
private
def create_post_params
params.require(:post).permit :title, :body
end
end
Beside the controller, I also have a Post model with a title and a body. My question is what is this :post thing in params.require(:post).permit :title, :body? I write it as :post, is it because I'm currently inside the PostsController? Or I'm reading the properties of a Post?
Edit
Based on gdpelican's answer, if my new.html.erb is like this:
<h1>Create a post</h1>
<%= form_for :post, url: posts_path do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
<p class="help-block">Please type the title of the post</>
</div>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: "form-control", rows: 5 %>
<p class="help-block">Please type the body of the post</>
</div>
<%= f.submit class: "btn btn-primary" %>
<% end %>
It's the :post part in <%= form_for :post, url: posts_path do |f| %> determines that I should use :post in params.require(:post).permit :title, :body, right?
Your parameters (typically) look like this
{"utf8"=>"✓", "authenticity_token"=>"...", "post"=>{"title"=>"My title", "body" =>"Body of my Post"}}
When you require a specific key from the parameters (for example post) Rails will throw an error if the hash it was passed doesn't have "post"=>{....}, then once it passes that check it permits the allowed keys and returns only the parameters nested under "post" hash allowed. To copy the api docs examples
params = ActionController::Parameters.new({
person: {
name: 'Francesco',
age: 22,
role: 'admin'
}
})
params.require(:person).permit(:name, :age)
=>{"name"=>"Francesco", "age"=>22}
So after your strong params check, the return is a hash of :post parameters that you have allowed.
EDIT: To answer your second question.
That is one way of thinking about it. Your form syntax (form_for :post) is creating the post hash with the attributes nested inside, and sending it as part of the overall parameters hash. And your params.require(:post) is taking the entire params, and finding only the hash key it wants (post) and then permitting the keys that are inside the post hash.
It is the name of the JSON wrapper of your form values.
The form will typically wrap the form parameters like so:
{
post: {
title: "Title",
body: "Body",
}
}
When using something like form_for #post
In essence, params.require(:post).permit(:title, :body) is saying two things:
my parameters must have a :post attribute
the :post attribute may only have a title and a body parameters, and nothing else.
UPDATE
The parameters in form_for are what affect how your parameters are wrapped.
Generally, the name of the controller matches the name of the form parameters, so in most instances it's a safe assumption that a 'BooksController' will accept form parameters in a 'book' field.
I have 2 models, Posts and Comments. I would like to create a button on the Post show view which directs it to Comment new action. So I create a new action in Post:
def comment
#post = Post.find(params[:id])
redirect_to new_comment_path
end
I want to save the post_id in the Comment models, so I create d hidden field in the new comment form:
<div class="field">
<%= f.hidden_field :post_id, :value => #post.id %>
<%= f.label :body %><br />
<%= f.text_field :body %>
</div>
But error appeared: "Called id for nil".
I am very new, can anyone help? Or should I use other approach?
Well you are missing to pass the value,
I had tried out this way and it works, for your example.
edited:
redirect_to :controller=>'comments', :action=>'new_comment', :post_id=>#post.id
receive as #post_id = params[:post_id]