I appreciate help with this issue. I have been a bunch and trying different options but to no avail.
I have tasks folder with an index and a form partial that I render on the tasks/index page <%= render"form_tasks" %>. When I submit a task on the index page, everything works fine and the task gets added. I have also included the form partial on a global modal that displays from the nav <%= "tasks/form_tasks" %>. the idea being I want to be able to add a task no matter where you are on the site. Except, if I am anywhere on the site outside of the /tasks folder, I get an error.
ActionController::ParameterMissing in TasksController#create
param is missing or the value is empty: tasks
def tasks_params
params.require(:tasks).permit(:task, :details)
end
in my tasks controller I have
def create
#task = tasks.new(tasks_params)
if #task.save
flash[:notice] = "Task Recorded"
redirect_to task_index_path
end
end
private
def tasks_params
params.require(:tasks).permit(:task, :details)
end
Thanks in advance!
Related
I'm trying to build a profile page that displays posts sent only to the requested user, and allows the visitor to write a post of their own. Because this simplified example should have two distinct controllers: users and posts, I made partials for each post action to render within the user's show action.
Directory structure for my views directory looks like this:
- posts
- _index.html.erb
- _new.html.erb
- users
- show.html.erb
... (etc.)
Section that displays these partials within the user's show.html.erb:
<section>
<h3>Posts:</h3>
<%= render '/posts/new', :post => Post.new %>
<%= render '/posts/index', :posts => Post.where(target_id: params[:id]) %>
</section>
I eventually found out that you could pass variables into the partial in this render line, and though this works, it's very messy and probably doesn't follow the best practices.
Ideally, I'd want these partials to be connected with the posts controller so I can write more complex database queries in a place that isn't the view:
class PostsController < ApplicationController
def new
#post = Post.new
end
def index
#posts = Post.where(target_id: params[:id])
end
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
#post.target_id = params[:post][:target_id]
if #post.save
redirect_to :back, notice: 'You published a post!'
else
render new
end
end
private
def post_params
params.require(:post).permit(:body)
end
end
Currently, I haven't found a way of doing this. I know this is a newb question, but thanks for any help in advance.
You are attempting to treat your controllers like models: doing the post work in post controller and the user work in user controller. But controllers are task-oriented, not model-oriented.
Since you want posts info in your user form, it's typical to gather it in the user controller. E.g.
class UsersController < ApplicationController
def show
...
#posts = Post.where(user_id: user.id)
end
end
That #posts instance variable is visible in the show template and any partials it calls. But many coders prefer to send it explicitly through render arguments, as more functional:
<%= render '/posts/post_list', posts: #posts %>
For one thing it's easier to refactor when you can see at a glance all of the partial's dependencies.
I agree somewhat with #Mori's advice. As he said, you are trying to put too much logic into the controller. I think this was a result of you trying to get it out of the view, which is the right idea, but you want business logic to be in the model.
Also, those index and new actions for PostsController are never going to be called. When you are calling the render posts/new for example, that is rendering the view, not the controller action. So, those controller actions have no reason to exist.
I would implement the fix in perhaps a different way than Mori described. It's a recommended practice to try and pass as few instance variables from the controller to the view as possible (see 3rd bullet in the linked section).
Since it's really the show action of the UsersController we are talking about here, I as someone trying to understand your code would assume the instance variable you are passing to the show view is something like #user.
You may want to use an includes method when instantiating the #user object. The includes statement will allow you to load the additional models you will need to instantiate using the minimum number of queries possible (preventing an N+1 query situation). You probably don't want to load every single one if there are thousands of matching posts, so I put an arbitrary limit of 10 on that.
UsersController
def show
#user = User.find(params[:id]).includes(:received_posts).limit(10)
end
#....
View
<section>
<h3>Posts:</h3>
<% unless #user.id == current_user.id %>
<%= render 'posts/form', post: Post.new(user_id: #user.id) %>
<% end %>
<%= render #user.received_posts %>
</section>
Putting the partial for a new post instead as a view called posts/form will allow you to reuse that form if you want to render an edit action (form_for knows which action to use on submit by calling the passed model's persisted? method).
Note that this code assumes the User model has the second relationship with posts set up to be called received_posts, but you can change it to whatever reflects the reality. By passing the received_posts collection to the render method, Rails is smart enough to know that if you want to render a collection of Post models to look for a posts/_post partial and render one for each Post. It's a little cleaner looking IMO. Just make sure to move your posts/show code into that. posts/show implies this is its own action and not something used as a partial for something else.
I am making an auction site and have been scratching my head trying to figure out how to best deal with auction/product creation. What I have come up with, and it may be a horrible idea, is to have a List Item link that, when clicked, posts to the create action for the auctions controller and then redirects to the edit page for that auction.
The reason I want to do this is because I feel it will make adding photos to the product at creation time easier and I can save the state of the auction so that they can come back and finish it later if they want.
The question:
How do I make a link post to the create action and then redirect to the edit page for the newly created item?
Let me know if there are any specific files you need to see, but I don't really have any code to go off of since I haven't made my create and edit actions yet or the routes
If you are using form_for in your view, you can change the destination url and set the method to post like this:
<%= form_for #auction, { :url => auction_path, :method => :post } do |f| %>
... Create your form ...
<% end %>
Then in the controller:
def create
#auction = Auction.new(params.require(:auction).permit(< list your parameters here>))
if #auction.valid?
#auction.save
flash[:notice] = 'New Auction created successfully.'
redirect_to 'edit'
else
render 'new'
end
end
I feel like this is simple but I'm banging my head against the wall. I'm trying to tell my Rails app that if one parameter is present (signature in this example) that I want to redirect home. Here's my code:
<%= if #pc.signature.present? %><% redirect_to "pages#home" %><%end%>
I keep running into a syntax error. This is in the edit.html.erb file by the way.
Perhaps in your controller you didn't define #pc? also, use path instead of 'pages#home'. it should look more like this:
def edit
#pc = Pc.find(params[:id]) #or whatever your logic is
redirect_to root_path if #pc.signature.present?
# otherwise 'edit' template will be rendered
end
You need to do that on your action controller, not in the view
def your_action
if #pc.signature.present?
redirect_to 'your_path_or_url'
end
end
I am working on an application where one controller controls the create action of several models. I have a lot more code, but I'm not sure if this error is specific to code or a generic fix (like changing the HTTP request) that doesn't require me to post my entire set up.
I have a 'basketball' model that belongs_to 'activities' that is generated from the activities controller. Each activity has_one basketball model.
Then in the basketballs controller I have this.
def edit
#activity = Activity.find(params[:id])
#basketball = #activity.basketball
end
def update
#activity = Activity.find(params[:id])
#basketball = #activity.basketball
if #basketball.update_attributes(basketball_params)
flash[:notice] = "Activity has been updated."
redirect_to activities_path
else
flash[:notice] = "Activity has not been updated."
render 'edit'
end
end
However, when I click the update button, my page renders a blank page with all of the parameters in the url. Example:
http://0.0.0.0:8080/basketballs/10/edit?utf8=%E2%9C%93&_method=patch&authenticity_token=[token]&basketball
Does anyone know how to fix this?
You have 3 nested forms in your views.
Here are the problems: app/views/strengthworkouts/_formatting.html.erb line 65 and app/views/workouts/_strengthworkout.html.erb line 5
Remove those <form> tags, keep the form_for.
Only the outermost form was used. And because it doesn't have any action or method or whatsoever attribute, submitting it just triggers a GET to the current path with the params in the query string.
I'm building a webapp that features a UI split into two sides, a menu bar and a content area.
The menu bar has a listing of the titles of all blogs that a user has written. When a title is clicked, the content area should change to show the posts of that blog.
1.) So on my menu bar, I have:
<%= link_to blog.title, blog, :remote=>true %>
And in my content area, I have:
<div id="contenthere"></div>
2.) So by my understanding, this should trigger the show method of the blog controller. There, I have the following in the method:
#blog = Blog.find(params[:id])
respond_to do |format|
format.js { render :show_blog }
end
3.) Which should go look for a file called show_blog.js.erb in views/blogs folder:
$("#contenthere").html("<%=escape_javascript(render :partial=>"show_blog")%>");
Which will take my div with commenthere id and render the _show_blog.html.erb partial (located in the blog view folder) with the blog parameter equal to the #blog parameter that was set in my blog controller.
4.) So my show blog partial has this code:
<%=#blog.title %>
<%=#blog.user_id %>
EDIT: Actually, I search around and found out that I can't use the method 'render' from within the assets folder-- where do I put the js.erb then? I've moved it to the blog view folder, home view folder (index.html.erb), and just the /view/ folder... The error is gone, but the link is not working...
EDIT: Put the show_blog.js.erb in my views/blogs folder, since it's the blog controller calling it. Nothing happening when I click the link and no JS errors shown in console. Is the js being called at all?
EDIT: Changed to reflect my final answer.
#blog = Blog.find(params[:id])
respond_to do |format|
format.js { render :show_blog }
end
That is not Rails default logic.
You didn't provided, how method is called, suppose
def show_blog
#blog = Blog.find(params[:id])
respond_to do |format|
format.js
end
end
Then, Rails will look for show_blog.js.erb in views/blogs and render that file.
Also, you need to pass actual instance to partial, because patrial is stand-alone chunk of code and doesn't know, what #blog is:
$("#contenthere").append("<%=j render :partial=>"show_blog", :locals=>{:#blog=>#blog}%>");
Very simple solution in the end--- The partial was calling for blog.title, blog.user_id, but #blog was the actual param that was passed. Just had to change to #blog.title and #blog.user_id.