I'm just starting to learn Rails so please forgive the dumb question. In my web app, I was able to set up working models, forms, and view. A user is able to input their decimal answer and it shows on the web page perfectly. However, I want to subtract one user input from another user input. So if the user inputs 100 in one model "post.price" and 10 in another input model "ratings1.content" > I want it to show 90 in the "fprice.content3". Any help that you guys can give me would be so amazing, I feel like the issue might be in my controller for fprice. I have listed below all my relevant code. Thank you again :)
_form.html "post.price"
<%= simple_form_for #post do |f| %>
<%= f.input :title %>
<%= f.input :image %>
<%= f.input :price %>
<%= f.button :submit %>
<% end %>
_form.html "ratings1s.content"
<%= simple_form_for ([#post, #post.ratings1s.build]) do |f| %>
<%= f.input_field :content %>
<% end %>
_form.html "fprice.content3"
<%= simple_form_for ([#post, #post.fprices.build]) do |f| %>
<%= f.input_field :content3 %>
<% end %>
Rails Controller "fprices"
class FpricesController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#fprice = Fprice.create(params[:fprice].permit(:content3))
#fprice.content3 === #post.price - #ratings1.content
#fprice.user_id = current_user.id
#fprice.post_id = #post.id
if #fprice.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
Rails Controller "ratings1s"
class Ratings1sController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#ratings1 = Ratings1.create(params[:ratings1].permit(:content))
#ratings1.content *= 10
#ratings1.user_id = current_user.id
#ratings1.post_id = #post.id
if #ratings1.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
It appears that at no point in time are you every defining #ratings1 object, then you call the content method on it while the value of #ratings1 is nil and thats what cause the error. Maybe something like this should help:
class FpricesController < ApplicationController
before_action :authenticate_user!
def create
#post = Post.find(params[:post_id])
#fprice = Fprice.create(params[:fprice].permit(:content3))
#ratings1 = #post.ratings1s.last
#fprice.content3 = #post.price - #ratings1.content
#fprice.user_id = current_user.id
#fprice.post_id = #post.id
if #fprice.save
redirect_to post_path(#post)
else
render 'new'
end
end
end
I think this line is also a the problem
#fprice.content3 === #post.price - #ratings1.content
=== is an equality operator so I don't know why you would have it there replace it with this
#fprice.content3 = #post.price - #ratings1.content
Related
Can someone help me make a form? I keep getting ActionView::Template::Error (undefined method `title' for #):
UrlsController
'''
class UrlsController < ApplicationController
def url_params
params.require(:url).permit(:title, :link)
end
def create
#url = Url.create!(url_params)
flash[:notice] = "#{#url.title} was successfully created."
#url.save
end
def new
#url = Url.new
end
def edit
#url = Url.find(params[:id])
end
def update
#url = Url.find params[:id]
#url.update_attributes!(url_params)
flash[:notice] = "#{#url.title} was successfully updated."
end
end
'''
new.html.erb
'''
<h2>Add A URL Reference</h2>
<%= form_for Url.new do |f| %>
<%= f.label :title %><br />
<%= f.text_field :title %>
<%= f.label :link %><br />
<%= f.text_field :link %>
<%= f.button :submit %>
<% end %>
'''
I would suggest you refactor your code like this..
You can take note of the set_url in the private to prevent repetition of codes
class UrlsController < ApplicationController
before_action :set_url, only: [:show, :edit, :update, :destroy]
def new
#url = Url.new
end
def edit
end
def create
#url = Url.new(url_params)
if #url.save
flash[:success] = Your url was successfully published!]
redirect_to #url
else
render :new
end
end
def update
if #url.update(url_params)
flash[:success] = Your url was successfully updated!]
redirect_to #url
else
render :edit
end
end
private
def set_url
#url = Url.find(params[:id])
end
def url_params
params.require(:url).permit(:title, :link)
end
end
new.html.erb
<h1>New Form</h1>
<%= render 'form', url: #url%>
_form.html.erb
<%= form_for #url do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :link %>
<%= f.text_field :link%>
<%= f.submit %>
<% end %>
routes.rb
resources :urls
You will want to check devise documentation if you'll be using devise for authentication.
You used create with a bang(!) in #url = Url.create!(url_params).
It raises an exception when the record is not created.
Hence if #url is not created it will throw an error and when you call title on the instance.
As #Tolase Adegbite suggested.
Remove the code with bang. Initialise the object then call a save without bang operator.
If you wish to use bang use a begin and rescue block.
I have a provider model which has many comments. I have a current setup working with the form being:
views/comments/_form.html.erb
<%= form_for([#provider, Comment.new] ) do |f| %>
<%= f.text_area :body, cols: 30, rows: 4, class: 'form-control' %>
<%= f.hidden_field :user_id, value: current_user.id, class: "form-control" %>
<div>
</br>
<%= f.submit :post, class: 'btn btn-primary btn-lg' %>
</div>
<% end %>
But I dont think its right from what iv seen around it should be
<%= form_for([#provider, #comment[) do |f| %>
but this method I get the following error
First argument in form cannot contain nil or be empty
I access my comments form from within my provider show.html.erb like this
<%= render 'comments/form', provider: #provider %>
My comments views are just _form.html.erb and _comments.html.erb which lists all the comments for a given provider.
My comments_controller.rb is as follows
class CommentsController < ApplicationController
before_action :set_provider
def new
#comment = Comment.new
end
def create
#provider = set_provider
#comment = #provider.comments.create!(comment_params)
redirect_to #provider
end
def destroy
#provider = set_provider
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to #provider
end
private
def set_provider
#provider = Provider.find(params[:provider_id])
end
def comment_params
params.require(:comment).permit(:body, :user_id)
end
end
If anyone point me in the right direction that would be very much appreciated.
Found the issue.
Because I was showing the Comments in the show action of my provider model I needed this in the Provider
def show
#comment = Comment.new
#provider = find_provider
end
Works perfectly now.
I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>
I am new to Rails and working on creating a generic "facebook" type of app as practice with users and posts associated with each user. However, I'm currently having an issue where I think the form that I am using to create the posts is also being rendered out as a blank post with no post ID where I display all of the posts in a section below. I think that this post is being shown even before it is being saved to the database.
Here is my code in my view:
<div class="newpostcontainer">
<div class="newposttext">
<%= form_for([#user, #user.posts.build]) do |f| %>
<%= f.text_area :post, size: "69x1" %>
</div>
<div class="newpostsubmitbutton">
<%= f.submit %>
</div>
<% end %>
</div>
<% #user.posts.reverse_each do |p| %>
<div class="postedcontainer">
<div class="minipostpic">
<%= image_tag #user.photo.url, width: 32, height: 32 %>
</div>
<div class="nameofposter"><%= #user.name %></div>
<div class="dateofpost"><%= p.created_at%></div>
<div class="postcontent"><%= p.id%></div> <br>
<div class="postcontent"><%= p.post%></div> <br>
<div class="likecommentdelete">
<%= link_to "Delete", [p.user, p], method: :delete %> | Like | Comment
</div>
</div>
<%end%>
</div>
Here is my controller:
def index
#user = User.find(params[:user_id])
#posts = #user.posts.all
end
def create
#user = User.find(params[:user_id])
#post = #user.posts.create!(post_params)
redirect_to user_path(#user)
end
def show
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
redirect_to user_path(#user)
end
def destroy
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
#post.destroy
if #post.destroy
redirect_to user_path(#user)
else
redirect_to users_path
end
end
private
def post_params
params.require(:post).permit!
end
end
And here is my model:
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
validates_presence_of :post
end
I'm pretty sure the issue has something to do with my form to create the new post because when I remove it or comment it out, the extra blank post with no post ID goes away.
Any thoughts or suggestions?
Thank you!!
I think you need to permit the field values to be posted:
i.e.,
params.require(:post).permit!
should be
params.require(:post).permit(:name, :post)
then only it will POST I think.
Hope it helps :)
This is because of rails 4 strong parameter feature. You need to whitelist your active models parameters. For more details refer to here.
In your case you need to do something like this:
params.require(:post).permit(:post)
where the ":post" inside require is your model and the other one is your permitted field that is your textarea.
Several issues -
Form
<%= form_for([#user, #user.posts.build]) do |f| %>
Why are you building an associative object? #user.posts.build will not persist your data, and will cause all sorts of non-conventional issues I would highly recommending building the posts associative object in your controller's new action before using in the view, so you can do this:
#app/controllers/users_controller.rb
def new
#user = current_user
#user.posts.build
end
<%= form_for #user do |f| %>
Association
You're trying to edit the post attribute with this statement:
<%= f.text_area :post, size: "69x1" %>
This won't work in any circumstance, as :post is an association, not an object. Rails only allows you to change / add attributes to specific objects, which means you'll be better doing something like this:
<%= f.fields_for :posts do |p| %>
<%= p.text_area :title %>
<%= p.text_area :body %>
<% end %>
Strong Params
You're currently permitting all your params? You'll be better doing this:
def post_params
params.require(:user).permit(posts_attributes: [:title, :body])
end
Use Posts Controller
A better way will be to just use the posts_controller, like this:
#app/controllers/posts_controller.rb
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
end
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<% end %>
My app has a user model and a post model, where user has_many posts and posts belong_to users. Posts are displayed on a user's profile page. I'd like for any user to be able to post on his own, or any other user's profile page. However, the problem I'm having is that while I know who is posting (current_user), I don't know whose profile current_user is on. I need to know this in order to assign the new post to that user's posts. How do I extract user id information from the profile currently being viewed, so I know where to assign the new post?
My micropost controller looks like:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find_by_name(params[:id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
But I'm getting a NoMethodError: undefined method `microposts' for nil:NilClass. I assume this is because I'm making some mistake with the creation of the user_of_page variable, but I don't know what that is!
SOLUTION
Thanks Sam. I took your advice and ended up doing it like this:
I added a column to my Micropost table called belongs_to_id.
I then passed the id of the user whose profile is being shown from the user show view to the micropost controller using a hidden field in the micropost form, like so:
<%= form_for #micropost do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :content, "Why that mood?" %>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.hidden_field :author, :value => current_user.name %>
<%= f.hidden_field :belongs_to_id, :value => #user.id %>
<%= f.hidden_field :agree, :value => "0" %>
<%= f.hidden_field :disagree, :value => "0" %>
<%= f.hidden_field :amused, :value => "0" %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
I then used this id value to search for the user to assign the post to, in the micropost controller, like so:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find(params[:micropost][:belongs_to_id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
Magic! Thanks again, you helped me to see it in the right way.
I would do it like this:
class profiles_controller < AC
...
def show
#profile = User.find(params[:id]).profile || current_user.profile
#post = Post.new
end
..
end
/profiles/show.html.erb
...
Name: <%= #profile.full_name %>
...
<%= form_for #post do |f| %>
<%= hidden_field_tag #profile.user %>
...
<% end %>
class microposts_controller < AC
def create
profile_user = User.find(params[:user_id]) # Owner of the profile current_user is on
..
end
end
Not tested. Hope this helps.