Missing Params on Post in Rails? - ruby

I'm learning Ruby on Rails at the moment and we're making a blog app to learn about crud actions and such and I'm stuck on this create method in my controller not working as it does in the course. I'm having trouble the create method in this controller:
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
end
def index
#articles = Article.all
end
def new
end
def create
#article = Article.new(params.require(:article).permit(:title, :description))
#article.save
redirect_to #article
end
end
I get this error when trying to create an article:
ActionController::ParameterMissing in ArticlesController#create
param is missing or the value is empty: article
It seems to be getting hung up on the first line of the create method but I'm not sure why it doesn't think there's an article... Here's my new article view as well for further reference:
<h1>Create a new Article</h1>
<%= form_with scope: #article, url: articles_path, local: true do |f| %>
<p>
<%= f.label :title %><br/>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br/>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>

Check whether your parameters coming under hash with key article like this -
{"article"=>{params}}
Also initiate Article object in new action.
You can redefine the params to permit like this:

in controller new method create object
#article = Article.new
and in form HTML add one more option use method: "post"

Related

Trying to get nested objects to be given parent ids

Alright, So I have days, tracks, and events. When I create a track, it is given the proper day_id along with its own track_id . When I try to create an event, I want it to be given the appropriate day_id and/or track_id.
So when I pull up a day it should only show the tracks and events that as associated with the day. An event should exist in a track, which exists in a day.
So, this is basically a calendar that shows a daily schedule of different tracks, and the events within the tracks.
Also, my events table in my db has a track_id and a day_id.
Here is my routes.rb
resources :days do
resources :tracks do
resources :events
end
end
My new/create methods from my events_controller.rb
def new
#day = Day.find(params[:day_id])
#track = Track.find(params[:track_id])
#new_event = Event.new
end
def create
#day = Day.find(params[:day_id])
#track = Track.find(params[:track_id])
#events = #track.events
#new_event = Event.new(params.require(:event).permit(:name,:start_time, :end_time))
if #new_event.save
flash[:notice] = "Saved"
redirect_to #day
else
flash[:error] = "Error"
render :new
end
end
And here is where I am trying to create a new event in my events.new.html.erb
<%= form_for [#day, #track, #new_event] do |f| %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', placeholder: "Enter the event" %>
<%= f.label :start_time %>
<%= f.text_field :start_time, class: 'form-control', placeholder: "Enter a start time"%>
<%= f.label :end_time %>
<%=f.text_field :end_time, class: 'form-control', placeholder: "Enter a start time"%>
<%= f.submit "Save", class: 'btn btn-success' %>
<% end %>
Thanks for the help, I'm pretty sure I attached everything that was needed!
You should create the event from the track:
#new_event = #track.events.new
This will create an event with already the appropriate track_id inside.
However, this does work...
#new_event = #track.events.new(params.require(:event).permit(:name, :start_time, :end_time))

Ajax and Ruby on Rails with local variable?

I really don't get how to use Ajax with Ruby on Rails. I must be missing something simple.
What I want to do is to ask the user to select a date, and then make a table of documents appear, but only with the selected date (Date is an attribute of Document).
My idea is to create a local variable witch is not in my database, store the selected date in it, and then create a loop in my view saying for example #document.where(:date = date).each...
In app/controllers/documents_controller.rb, I have :
class DocumentsController < ApplicationController
def information
#documents = Document.all
#date = params[:date]
respond_to do |format|
format.html # index.html.erb
format.js{}
format.json { render json: #documents}
end
end
end
And in app/views/documents/_information.js.erb, I have:
<%= form_tag(document, :remote => true) do %>
<%= label_tag(:date, "The selected date is:") %>
<%= text_field_tag(:date) %>
<%= submit_tag %>
<% end %>
In the end, I have a field where the user puts his date, but the submit button doesn't do anything.
What do I miss ?
As discussed you need to change the flow of your app.Lets go through steps one by one
a. create your input field where you are selecting your date field. You already have your form for that
<%= form_tag(you_path_for_information_method, :remote => true) do %>
<%= label_tag(:date, "The selected date is:") %>
<%= text_field_tag(:date) %>
<%= label_tag(:portfolio, "Add portfolio") %>
<%= text_field_tag(:portfolio) %>
<%= submit_tag %>
<% end %>
In controller
def information
#documents = Document.all
#date = params[:date]
#portfolio = Portfolio.find(params[:portfolio])
respond_to do |format|
format.js{}
end
end
In your information.js.erb you can have:
$("#some_id_of_parent").html("<%=j render partial: "your_partial", locals: {portfolio: #portfolio} %>")

Not showing created blog entries

I'm fairly new to Rails and learning to create a blog using this tutorial. On step 10, once I define create and show, after creating a new post in browser I don't see any entries on show with id page. All I see is heading and and blank title and post header.
Following is my controller -
class PostController < ApplicationController
def index
end
def new
end
def create
#post = Post.new(params[:posts])
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
end
Show view ---
<h1>Show a post</h1>
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
Route ---
RailsBlog::Application.routes.draw do
resources :post
root :to => "post#index"
end
Form ---
<%= form_for :post, url: {action: 'create'} do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit 'Submit' %>
</p>
<% end %>
May be this is just a spelling mistake, but since I've recently started learning Rails, I'm unable to resolve this.
Update: I can go to particular id using
http://localhost:3000/post/1
but am only seeing blank page with view headers
The problem is here:
#post = Post.new(params[:posts])
It should be params[:post] - singular, not plural.
Also note that the best practice with form_for is to pass an object instead of symbol:
form_for #post do |f|
Then:
You don't need to specify url
You can reuse the same form for an edit action or create action (if object creation failed due to failing validation)
This however requires to initialize new object in your new action:
def new
#post = Post.new
end
UPDATE:
Also your routes are incorrect. When defining plural resources, you need to use plural form (it's more the convention than requirement, but since you're learning stick with it). So change your routes to:
resources :posts
And rename your controller to PostsController (remember to rename file name as well). restart the server and all should work.
ANOTHER UPDATE:
You also need to rename folder app/views/post to app/view/posts.
AND YET ANOTHER UPDATE:
In rails 4, you are not allowed to mass assign any params which has not been whitelisted using strong parameters. You need to tell rails which fields you allow to be assigned first - this is a security thing. You need to make some changes to your controller:
class PostsController < ApplicationController
...
def create
#post = Post.new(post_params)
...
end
...
private
def post_params
params.require(:post).permit(:title, :text)
end
end
This is the way to tell your controller that you are expecting those attributes from your form and they can be safely assigned.
I had just similar problem on the same tutorial.
The code spelling was correct and clearly accorded to examples in tutorial and BroiSatse's answer above.
The mistake was in order of private method definition.
How it was:
...
private
def post_params
params.require(:post).permit(:title, :text)
end
def show
#post = Post.find(params[:id])
end
...
The working order:
def show
#post = Post.find(params[:id])
end
private
...
Anyway, this topic was rather helpful. Thak you for your answers!

2 instance variables of the same name in different controllers

I finished Michael Hartl's Ruby on Rails Tutorial. Now I'm working on the suggested exercises. The application he builds is basically a Twitter clone where one can post Microposts and they appear in your feed http://ruby.railstutorial.org/chapters/user-microposts#fig-micropost_created
The main page is in home.html.erb from the StaticPagesController and features a Micropost textbox where one can post Microposts. The code for the textbox looks like so:
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
The #micropost variable is initialized in the StaticPagesController like so:
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
end
end
Now inside the MicropostsController there's a create action like so:
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
My question is what is the purpose of the first #micropost variable as opposed to the second?
thanks,
mike
The first #micropost becomes available to the view rendered by the first controller method; the second #micropost becomes available to the view rendered by the second controller method. And it just so happens that the two methods are rendering the same view.
The only wrinkle is that since the second controller is conditional. If the create succeeds (passes validation and saves) then there's a redirect, so there's no proper view (although there will be in a moment, after the client-side redirect). But if it fails, then the view gets an object that contains the user-entered values as well as the validation errors which the view can then show to the user.

How can I use do edit-in-place on three different models from a View for a model those three belong_to?

I would like to enable edit-in-place functionality in a View that displays values from different models:
This is what I use currently and it does NOT work, but would like some alternatives:
I have a model called Campaign. In the controller, I do the following to list, in order, the three Models that belong_to a Campaign:
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% model_name = campaign_event.class.name.tableize.singularize %>
<p>
<%= link_to campaign_event.title, send("#{model_name}_path", campaign_event) %>
<span class='model_name'>(<%= model_name.capitalize %>)</span>
<%= campaign_event.days %> Days
</p>
<% end %>
campaign_event is a campaign_helper defined as:
module CampaignsHelper
def campaign_events
return (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
end
end
I want to be able to click on the numerical value for Days when looking at the view/campaign/show and edit the value for :days (in this case, displayed as campaign_event.days
I'm not really sure about it, but I'll try to help... I believe something like the following may work for you:
# calls controller
in_place_edit_for :call, :days
# emails controller
in_place_edit_for :email, :days
# letters controller
in_place_edit_for :letter, :days
# campaign view
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% controller_name = campaign_event.class.name.tableize %>
<% model_name = controller_name.singularize %>
<p>
<%= link_to campaign_event.title,
send("#{model_name}_path", campaign_event) %>
<span class='model_name'>(<%= model_name.capitalize %>)</span>
<%= in_place_editor_field model_name, :days, {},
:url => {
:controller => controller_name,
:action => 'set_#{model_name}_title',
:id => campaign_event.id} %> Days
</p>
<% end %>
There's somethings I don't know exactly how to do:
1) in_place_editor_field model_name
I believe this won't work, but I don't know how to pass the model_name.
2) :action => 'set_#{controller_name}_title'
Not sure about it also. Just doesn't look right.
Anyway, hope it helps you... and forgive me if this is completely stupid.

Resources