Param from form not saved - ruby-on-rails

I've the following view in RoR:
<%= form_tag(url_for :controller => 'posts', :action => 'create', method: "post") do %>
<label>Zawartość</label>
<%= text_area_tag(:content) %>
<br/>
<label>Użytkownik</label>
<%= collection_select(:user, :user_id, User.all, :id, :name ) %>
<br/>
<% end %>
And the action of controller:
def create
#post = Post.new
#post.content = params["content"]
#post.user_id = params["user[user_id]"];
#post.save!
end
Unfortunately, user_id is saved as null. What is strange, the html is generated properly:
<select name="user[user_id]" ... >...</select>
Why?

Fix your create action to:
def create
#post = Post.new
#post.content = params["content"]
#post.user_id = params["user"]["user_id"];
#post.save!
end
I suggest you read Accessing elements of nested hashes in ruby.

You should stick to convention:
#config/routes.rb
resources :posts
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#post = Post.new post_params
redirect_to #post if #post.save #-> needs "show" action which I can explain if required
end
private
def post_params
params.reqire(:post).permit(:content, :user_id)
end
end
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_area :content %>
<%= f.collection_select :user_id, User.all, :id, :name %>
<%= f.submit %>
<% end %>
This will allow you to access url.com/posts/new to create a new post

Related

Mistake with my routes for uploading an image

I'm trying to solve a really simple problem with my code. I want to upload image into a post, I use paperclip, and the last step is not working.
That is my controller :
class PostsController < ApplicationController
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
flash[:success] = "uccess!"
redirect_to post_path(#post)
else
flash[:error] = #post.errors.full_messages
redirect_to new_post_path
end
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :image, :prix, :adress, :description)
end
end
that my form :
<%= simple_form_for #post, url: root_path do |f|%>
<%= f.input :title, label: "Nom du plat" %>
<br>
<%= f.input :image, as: :file %>
<br>
<%= f.input :prix %>
<%= f.input :adress, label: "Localisation" %>
<%= f.input :description %>
<br>
<%= f.button :submit %>
<% end %>
and that my view :
<%= image_tag (#post.image.url(:medium)) %>
<br>
<%= #post.description %>
<br>
<button>
<%= link_to "Home", root_path %>
</button>
So if you go through, and you spot a stupid mistake, please let me know.
You're calling root_path as the helper in your form when you need to call the route for post. Run rake routes and look for the create action related to post, which should be the same as the get route for the show action.
This should not be root_path:
<%= simple_form_for #post, url: root_path do |f|%>

Rails form_for NoMethodError - can't find where broken path is

I try to make my CRM application works and can't figure out where broken part is.
When trying to create new contact, on link '/companies/1/contacts/new'
got 'NoMethodError in Contacts#new'.
Screenshot is attached, see code below. Please help to find mistake..
route.rb is:
Rails.application.routes.draw do
resources :companies do
resources :contacts do
member do
post :new
end
end
end
root 'companies#index'
end
Contacts Controller:
class ContactsController < ApplicationController
before_action :set_company
def index
#contacts = Contact.where(company_id: params[:company_id])
end
def new; #contact = #company.contacts.new; end
def create
#contact = #company.contacts.create(contact_params)
#contact.save ? redirect_to #company : render :new
end
private
def set_company; #company = Company.find(params[:company_id]); end
def contact_params
params.require(:contact).permit(:name, :position, :phone, :email)
end
end
View:
new.html.erb:
<%= render 'form' %>
<%= link_to 'Back', company_contacts_path %>
Form helper:
<%= form_for(#contact) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You need to specify the company as the first argument to form_for:
form_for(#company, #contact)
Then form_for will be able to infer the correct path.

undefined method `article_path'

this error is occuring and i have no idea why, thanks,
undefined method `article_path' for #<#:0x000001029cb960>
edit.html.erb
<h1>Editing <%= #article.name %></h1>
<%= form_for(#article) do |f| %> <-- ????something here?
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
articles model
class MediaController < ApplicationController
def index
#articles = Articles.all
end
def show
#article = Articles.find(params[:id])
end
def edit
#article = Articles.find(params[:id])
end
def update
#article.find(params[:id])
article_params = params.require(:article).permit(:name, :description, :location)
#article.update(article_params)
redirect_to #article
end
end
routes.rb
resources :media
patch "events/:id" => "media#update", as: "update_medium"
Change your routes to
patch "articles/:id" => "media#update", as: "update_medium"
And model name to singular like :
#articles = Article.all

How to access doubly nested models in rails?

I have a route that looks like this
resources :questions do
resources :answers do
resources :comments
end
end
However, when I try to build a comment
<%= form_for([#answer, #answer.comments.build]) do |f| %>
<p>
<%= f.label :comment %>
<%= f.text_area :comment, :cols => "50", :rows => "30"%>
</p>
<p>
I get undefined method comments. This is what my create comment looks like
def create
#answer = Answer.find(params[:answer_id])
#comment = #answer.comments.create(params[:comment])
redirect_to question_path(#question)
end
And answer has_many comments, and comments belongs to answer. Any ideas? Thanks!
You can access models from any controller in your app (just call Model.class_method)
Looking at your code, I'd recommend doing something like this:
#app/views/answers/show.html.erb
<% #answer.comments.each do |comment| %>
<%= comment.value %>
<% end %>
<%= form_for #new_comment do |f| %>
<%= f.text_area :comment, :cols => "50", :rows => "30"%>
<% end %>
#app/controllers/answers_controller.rb
def new
#answer = Answer.find(params[:id])
#new_comment = Comment.new
end
#app/controllers/comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.save
end
private
def comment_params
params.require(:comment).permit(:your, :attributes, :here)
end

Ruby on Rails / How to automatically add foreign key to my "comment" model?

I generate 3 models: "User", "Article" and "Comment", and the "Comment" model have foreign key "user_id" and "article_id". However I can't automatically add "article_id" when I want to create an comment to a specific article in view.
In rails console, I can add it successfully by using
comment = Comment.new(:content => "Great post")
comment.user = user
comment.article = Article.find(1)
comment.save
I tried to write some code in my controller, but is doesn't work
articles_controller.rb
class ArticlesController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
#comment = Comment.new()
end
def create
#article = current_user.articles.build(params[:article])
if #article.save
flash[:success] = "Article created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
#article.destroy
redirect_to current_user
end
private
def correct_user
#article = current_user.articles.find_by_id(params[:id])
redirect_to root_url if #article.nil?
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def create
#comment = current_user.comments.build(params[:comment])
if #comment.save
flash[:success] = "Comment created!"
redirect_to articles_url
else
render 'static_pages/home'
end
end
def destroy
#comment.destroy
redirect_to current_user
end
private
def correct_user
#comment = current_user.comments.find_by_id(params[:id])
redirect_to root_url if #comment.nil?
end
end
in view files
/articles/show.html file render a partial file "_comment_form.html.erb"
_comment_form.html.erb
<%= form_for(#comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose your comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
I can add some new lines to manually add article_id to the comments table. But it is not a good way.
<% #comment.article_id = #article.id %>
<%= form_for(#comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :article_id %>
<%= f.text_field :article_id %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose your comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
How can I do?
Thank you so much.
changed _comment_form.html.erb
# views/comments/_comment_form.html.erb
<%= form_for[:articles, #comment] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose your comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
The error:
SyntaxError in Articles#show
Showing F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb where line #2 raised:
F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb:2: syntax error, unexpected keyword_do_block, expecting keyword_end
...orm_for[:articles, #comment] do |f| #output_buffer.safe_conc...
... ^
F:/RailsProject/project/gamespace/app/views/comments/_comment_form.html.erb:9: syntax error, unexpected keyword_ensure, expecting $end
Extracted source (around line #2):
1:
2: <%= form_for[:articles, #comment] do |f| %>
3: <%= render 'shared/error_messages', object: f.object %>
4: <div class="field">
5: <%= f.text_area :content, placeholder: "Compose your comment..." %>
# comments_controller.rb
class CommentsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def create
#comment = Comment.new(comment_params)
#comment.article_id = params[:id]
if #comment.save
flash[:success] = "Comment created!"
redirect_to articles_url
else
render 'static_pages/home'
end
end
def destroy
#comment.destroy
redirect_to current_user
end
private
def correct_user
#comment = current_user.comments.find_by_id(params[:id])
redirect_to root_url if #comment.nil?
end
def comment_params
params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:id])
end
end
Error:
TypeError in CommentsController#create
can't convert Symbol into String
Rails.root: F:/RailsProject/project/gamespace
Application Trace | Framework Trace | Full Trace
app/controllers/comments_controller.rb:33:in `comment_params'
app/controllers/comments_controller.rb:7:in `create'
This error occurred while loading the following files:
comment
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"ybkPs+c2068AZIIqCNJz1epBtS4L1zgT/vU9LL2Fs+E=",
"comment"=>{"content"=>"sdfadfa"},
"commit"=>"Post",
"article_id"=>"10"}
-------------------------------------------------------------------------------
Solution:
# comments_controller.rb
def create
comment = current_user.comments.build(params[:comment])
comment.article = Article.find(params[:article_id])
comment.save
end
use hidden_field method
# views/_comments_form.html.erb
<%= form_for [#article, #comment] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :article_id, :value => #article.id %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose your comment..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
I was going to write a long post here, but I actually agree with Monk_code - you'll be better to inject the foreign_key into the new record rather than playing around with any tricks
#app/controllers/comments_controller.rb
def create
comment = Comment.new(comment_params)
comment.article_id = params[:id]
comment.save
end
OR
#app/controllers/comments_controller.rb
def create
comment = Comment.new(comment_params)
comment.save
end
private
def comment_params
params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:id])
end
Associative Data
The problem I can see is that your model will probably look like this:
#app/models/comment.rb
Class Comment > ActiveRecord::Base
belongs_to :article
belongs_to :user
end
If this is the case, you have to remember that you're saving data which is dependent on a parent model. As it's a dependency, it will not automatically know the foreign key, meaning you'll have to assign it yourself
If you were saving a new Article, you'll be able to pass accepts_nested_attributes_for or even just create a comment record after_create
Correctly Designing Your Application
My solution is to use the params[:id] you'll likely have in place as a result of using
resources :articles do
resources :comments
end
This means every comment will have to be created on an article's page, thus allowing you to use the params[:id] variable when you create a new record
Update
class CommentsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
#before_filter :correct_user, only: :destroy
def new
#comment = Comment.new
end
def create
#comment = Comment.new(comment_params)
if #comment.save
flash[:success] = "Comment created!"
redirect_to articles_url
else
render 'static_pages/home'
end
end
def destroy
#comment.destroy
redirect_to current_user
end
private
def comment_params
params.require(:comment).permit(:content).merge(:user_id => current_user.id, :article_id => params[:article_id])
end
end
you need something that
comment = Comment.new(:content => "Great post")
comment.user = user
comment.articles << Article.find(1)
comment.save
use << instead =
read this and about has_many

Resources