RoR: How can I get my microposts to show up? - ruby

Here is the users show view where they are supposed to show up. ..
<section>
<div id= "purchases">
<%= render 'shared/micropost_form_purchase' %>
</div>
<div id="sales">
<%= render 'shared/micropost_form_sale' %>
</div>
</section>
<%= #sales %> <%# This is just to see if it outputs anything. It doesn't :( %>
<div id="purchases list">
<ol class="microposts">
<%= render #purchases unless #purchases.nil? %>
</ol>
</div>
<div id="sales list">
<ol class="microposts">
<%= render #sales unless #sales.nil? %>
</ol>
</div>
so the forms (partials) are loading fine, but then when I make a post, in either one, neither the purchases list nor the sales list shows up. I checked the database and they are being created along with an entry in the column indicating kind (either sale or purchase).
Here are the forms:
<%= form_for (#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "purchase" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
and
<%= form_for (#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "sale" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
also, here is the show part of the users_controller.rb
def show
#user = User.find(params[:id])
#micropost=Micropost.new
#microposts = #user.microposts.paginate(page: params[:page])
end
and here is the show part of the microposts_controller.rb
def show
#micropost = Micropost.find(params[:id])
#microposts = Micropost.where(:user_id => #user.id)
#purchases= #microposts.collect{ |m| m if m.kind == "purchase"}.compact
#sales = #microposts.collect{ |m| m if m.kind == "sale"}.compact
end
additionally, with the help of this post (http://stackoverflow.com/questions/12505845/ruby-error-wrong-number-of-arguments-0-for-1#12505865) the variables #microposts, #purchases, and #sales are all outputting correctly in the console.
can anyone help me out?
edit: using scopes as suggested by the answer given works in the console (it outputs everything correctly, but they still don't show up in the view. Does this mean it is something wrong with my syntax for the users show page?
edit 2:
Here is the view/microposts/_micropost.html.erb code
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete,
confirm: "You sure?",
title: micropost.content %>
<% end %>
</li>

I'm making some assumptions without seeing more of your code, but it looks like you could
write what you've shown a little differently. I'm assuming your databases are migrating
and have the required columns, e.g., Micropost#kind, Micropost#user_id, etc.
You can use scopes to refine a collection of microposts more expressively. It might be helpful to read
up about ActiveRecord scopes: http://guides.rubyonrails.org/active_record_querying.html#scopes.
class Micropost < ActiveRecord::Base
belongs_to :user
scope :purchases, where(:kind => "purchase")
scope :sales, where(:kind => "sale")
# your code
end
I'm also assuming your user has many microposts:
class User < ActiveRecord::Base
has_many :microposts
# your code
end
For your forms, I'd suggest attaching your hidden field to the form object (f.hidden_field) so
you don't have to specify the name as 'micropost[kind]'.
<%= form_for(#micropost) do |f| %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= f.hidden_field :kind, :value => "sale" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
In MicropostsController#show, you can use your new scopes:
def show
#micropost = Micropost.find(params[:id])
#microposts = #user.microposts
#purchases = #microposts.purchases
#sales = #microposts.sales
end
You should also confirm that your MicropostsController#create action is actually adding
the microposts to the user sending the form (I'm assuming a current user method).
def create
#micropost = current_user.microposts.create(params[:micropost])
# yada
end
You can also confirm expected results on rails console after creating purchases or sales micropost with:
Micropost.purchases
Micropost.sales
Again, I could be missing something without seeing more of the code base.

Check Micropost.count, #purchases.count, #sales.count (by printing them in the controller, or some part of the view) to see if the records actually exist.
Also, if you want to render collections likes #sales and #purchases, you need to make sure that the model partial exists (_micropost.html.erb in your case). That is probably where you need to look for the view errors. For all you know, that file could be empty, thus no errors will show up at all.
The problem might also lie in your microposts#create (or whichever action that you are saving the micropost in), the micropost should be associated with the current_user:
#micropost = current_user.microposts.build(params[:micropost])
Taking this and your previous question into account, I suggest you go through the original code for the RoR tutorial again (and verify that all tests are passing) before taking it apart. You can always add new tests to it for your experiments and they will help in figuring out where you went wrong.

Related

Rails 4: Receiving the following error: First argument in form cannot contain nil or be empty

I am receiving the following error on a project of mine: First argument in form cannot contain nil or be empty. I am trying to create an edit page for my code. Fairly new with Rails and trying to learn without scaffolding.
Controller:
class BooksController < ApplicationController
def new
#book = Book.new
#authors = Author.all
end
def edit
#book = Book.find(params[:id])
end
def show
#Notice how the #books is plural here.
#books = Book.all
#authors = Author.all
##books = Book.where(id: params[:id])
end
#Create method will save new entries
def create
#book = Book.new(book_params)
#authors = Author.all
if #book.save
flash[:success] = "Book Added to Databse!"
redirect_to #book
else
render 'new'
end
end
private
#Note that this method will go up into the create method above.
def book_params
params.require(:book).permit(:title, :pub_date, :publisher, :author_id)
end
end
Model Page: (For Book)
class Book < ActiveRecord::Base
validates :title, :pub_date, :publisher, presence: true
validates :title, uniqueness: true
belongs_to :author
end
Model Page: (For Author)
class Author < ActiveRecord::Base
validates :name, presence: true
validates :name, uniqueness: true
has_many :books
end
Edit page:
<h1>Update a book entry</h2>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#book) do |f| %> **ERROR SEEMS TO BE RIGHT HERE!!!**
<%= render 'form' %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :pub_date %>
<%= f.text_field :pub_date, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :publisher %>
<%= f.text_field :publisher, class: 'form-control' %><br />
</div>
<div class="form-group">
<%= f.select(:author_id,
#authors.collect {|a| [ a.name, a.id ]},
{:include_blank => 'Please select an author'},
class: "form-control") %><br />
</div>
<%= f.submit 'Save Changes', class: "btn btn-primary" %>
<% end %>
</div>
</div>
Render form page (_form.html.erb)
<% if #book.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
<h2><%= pluralize(#book.errors.count, "error") %>
prohibited this entry from being saved:</h2>
<ul>
<% #book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
SHOW PAGE:
<div class="move">
<h1>Showing Book Titles:</h1>
</div><br />
<div class="row">
<% #books.each do |book| %>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<h2><%= book.title %></h2>
<h2><%= book.publisher %></h2>
<h2><%= book.pub_date %></h2>
<h2><%= book.author.name %></h2>
<h2><%= link_to "Edit", edit_path, class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
Here is my Log telling me what is wrong:
Started GET "/edit" for ::1 at 2015-08-14 16:49:17 -0400
Processing by BooksController#edit as HTML
Rendered books/edit.html.erb within layouts/application (2.2ms)
Completed 500 Internal Server Error in 9ms (ActiveRecord: 0.0ms)
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
3: <div class="row">
4: <div class="col-md-6 col-md-offset-3">
5:
6: <%= form_for(#book) do |f| %>
7: <%= render 'form' %>
8:
9: <div class="form-group">
app/views/books/edit.html.erb:6:in `_app_views_books_edit_html_erb___525891009649529081_70260522100960'
I will say that I have deleted the first 14 books from my data base and so the first book start on ID 14. Not sure if that matters.
Finally, I have tried adding all of these different instance variables to my controller in the edit method:
##book = Book.where(id: params[:id])
##book = Book.find_by_id(params[:id])
##book = Book.all
##book = Book.find_by_id(params[:id])
#book = Book.new(book_params)
#When I use the two below lines,
there are no error pages but create a new entry.
##book = Book.new
##authors = Author.all
Any Help will be appreciated! Thank you for your time!!!
This error means that the first argument to form_for is a nil value (in this case #book). Most of the times I've seen this, it's due to malformed controller actions, but that doesn't look to be the case here. From what I can tell, it's one of two things:
You're trying to edit a Book that doesn't exist. Do a .nil? check on it before deciding to render the form, and render an error message (or redirect) instead.
Your routes are broken, and the edit action is not rendering the edit view. This is most likely not the case.
EDIT:
After updating with your template for show, this looks like your problem:
<%= link_to "Edit", edit_path, class: "btn btn-primary" %>
I see two problems with this (though I'll need to see the output of rake routes to verify). Firstly, you need to pass an argument to the edit path (without them, where would your params come from?). Secondly, the default route for this would be edit_book_path.
Try this:
<%= link_to "Edit", edit_book_path(book), class: "btn btn-primary" %>
Assuming book ID 14 is in your database, you should be able to navigate to localhost:3000/books/14/edit if you created it with something like resources :books (documentation here). If this doesn't work, either your routes are not defined correctly or book with ID 14 does not exist in your database.
On your show view, change the link_to line to:
<%= link_to 'Edit', edit_book_path(book), class: "btn btn-primary" %>
So two changes:
Again, assuming book is a Restful resource, when you run rake_routes, you should see the path to edit is edit_book_path.
You need to pass the book instance with the path so Rails knows which object you wish to edit.
I found the correct syntax here.
Hope this helps.

Ruby on rails 4: showing error messages

I have trouble displaying error message for invalid inputs using Ruby on rails. If anyone can help me with it? Currently new to the area.
I suspect the area is due to :user and #user.
This is my form generated on index.html.erb
<%= form_for :user, url: '/login', html:{id:"form"} do |f| %>
<h2 class="login">Login</h2>
<div class="form">
<input type="name" placeholder="Name" name="user[name]" class="form-input" required /></div>
<% end %>
My ActiveRecord Model:
class User < ActiveRecord::Base
validates :name, :uniqueness => true
has_secure_password
end
I try to use the following error handling, by passing the following code after <%= form_for :user, url: '/login', html:{id:"form"} do |f| %> but it did not work with and showed:
NoMethodError in Users#register
: undefined method `errors' for nil:NilClass
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#article.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
You should be able to do something like this.
/app/views/shared/_error_messages.html.haml:
- if object.errors.any?
.alert.alert-danger
The form contains #{pluralize(object.errors.count, "error")}.
%ul#error_explanation
- object.errors.full_messages.each do |msg|
%li= msg
Then, wherever you want errors to be shown in your views, something like:
= render 'shared/error_messages', object: f.object
Note object in the method. When you call, you could pass either an object instance from your controller or (in the above case), the object of a form builder.

How to solve ParameterMissing error using ROR

Please help me to solve the below error.
Error:
ActionController::ParameterMissing in CustmersController#create
param is missing or the value is empty: users
When i am submitting the data,this error is coming.
My code is as follows
views/custmers/new.html.erb
<h1>Enter your data here</h1>
<center>
<%= form_for #users,:url => {:action => 'create'} do |f| %>
<% if #users.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#users.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #users.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<label for="name">Name:</label>
<%= f.text_field :name,placeholder:"Enter your name",:class => "input-field" %>
</p>
<p>
<label for="email">Email:</label>
<%= f.email_field :email,placeholder:"Enter your email",:class => "input-field" %>
</p>
<p>
<label for="phone">Phone no:</label>
<%= f.telephone_field :phoneno,placeholder:"Enter your phone number",:class => "input-field" %>
</p>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
<%= link_to "BACK",custmers_index_path %>
</center>
controller/custmers_controller.rb
class CustmersController < ApplicationController
def index
end
def new
#users=Custmer.new
end
def show
end
def create
#users=Custmer.new(user_params)
if #users.save
flash[:notice]="You have signed up successpully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="You have not signed up successfully"
flash[:color]="invalid"
render :new
end
end
private
def user_params
params.require(:users).permit(:name,:email,:phoneno)
end
end
model/custmer.rb
class Custmer < ActiveRecord::Base
EMAIL_REGEX = /\A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :name,presence:true,length: { minimum: 5 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :phoneno, presence: true,length: {minimum: 10}
end
I am using rails version-4.2.0 and ruby version-1.9.3.Please help me to resolve this error.
If you look at the stack trace accompanying your error, you could tell definitely where the problem is -- look for the first line in the stack trace that refers to your code (and not library code).
But a fair guess is the require(:users) line in your controller. It looks like you either copy/pasted this code from another controller, or changed the name of your controller after generating it as part of your scaffold.
It should be requires(:custmer) instead, as that is the class of the thing you're submitting.
As a general approach, you should follow the standard Rails practices for naming things, throughout. If you really want to use the misspelled, Custmer class, have at it, but use #custmr inside your controller and views to refer to an instance, not #users.

Save record in rails 4.0 using params hash

I'm trying to create a new record in rails using the form_for helper method. I think the params hash is blank because I keep getting blank errors when I submit the form.
This is my form:
<% provide(:title, "Add Department") %>
<h1>Add Department</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#department) do |f| %>
<%= render 'shared/department_error_messages' %>
<%= f.label :Full_Department_Title %>
<%= f.text_field :full_name %>
<%= f.label :Department_Abbreviation %>
<%= f.text_field :abbreviation %>
<%= f.submit "Add department", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
This is my departments controller
class DepartmentsController < ApplicationController
def show
#department = Department.find(params[:id])
end
def new
#department = Department.new
end
def create
#department = Department.new(params[department_params]) # Not the final implementation!
if #department.save
redirect_to root_path
else
render 'new'
end
end
private
def department_params
# This says that params[:department] is required, but inside that, only params[:department][:full_name] and
# params[:department][:abbreviation] are permitted. Unpermitted params will be stripped out
params.require(:department).permit(:full_name, :abbreviation)
end
end
This is the Model:
class Department < ActiveRecord::Base
validates :full_name, presence: true, length: { minimum: 6 }
end
When I submit, errors are rendered saying the full_name can't be blank (and the fields are now empty). The debug info is:
--- !ruby/hash:ActionController::Parameters utf8: ✓
authenticity_token: EjfYjWAzaw7YqVZAkCPZwiEMFfb2YLIRrHbH1CpZOwA=
department: !ruby/hash:ActionController::Parameters
full_name: Sports Department
abbreviation: SD
commit: Add department
action: create
controller: departments
I've also checked the development log. The transaction starts and is then rolled back. I can save a record in the console so I'm guessing its something to do with the params hash, but can't figure it out. Please help
This line:
#department = Department.new(params[department_params])
Should be:
#department = Department.new(department_params)
And, as a minor issue (but not causing this problem), your label tags should look like:
f.label :full_name, "Full Department Title"
This way they are correctly associated with the input.

Understanding Ajax in Rails 3

I thought I understood Ajax in Rails 3 to a point but think I am confusing myself somewhere or misinterpreted something. My understanding is that if I want to call different content on the same page then i create a js.erb file for that particular action. For example if i have an action of tynewyddnews, I will have an tynewyddnews view and a tynewyddnews.js.erb file.
I then create a partial to render on that page and call that partial in my .js.erb file.
Example
View
<% #tynewyddpost.each do |t| %>
<li>
<% single = t.photos.first %>
<a class="photo" href="#"><%= image_tag(single.avatar.url(:thumbnail_news_images)) %></a>
<p><%= link_to t.title, tynewyddnews_path(:type => 'tynewyddnews'), :post_id => t.id, :remote => true %></p>
<p class="date"><%= date_output(t.published_on) %></p>
</li>
<% end %>
<div class="post-item">
<h2><%= #tynewyddpostlatest.title %></h2>
<div id="work-samples">
<% for photo in #tynewyddpostlatest.photos %>
<%= image_tag(photo.avatar.url(:news_images), :class => 'work-sample') %>
<% end %>
</div>
<p class="post-description"><%= #tynewyddpostlatest.comments.html_safe %></p><a class="post-more" href="#">Continue Reading »</a>
<div class="post-item-panel">
<ul>
<li class="date">
<p><%= date_output(#tynewyddpostlatest.published_on) %></p>
</li>
</ul>
</div>
</div>
So the historical posts go down the left hand side and the latest post goes in the center
.js.erb
<% if params[:type] == 'tynewyddnews' %>
jQuery('.post-item').html('<%= escape_javascript(render partial: 'tynewyddnewspost') %>');
<% end %>
Partial
<div class="post-item">
<h2><%= #tynewyddpost.title %></h2>
<div id="work-samples">
<% for photo in #tynewyddpost.photos %>
<%= image_tag(photo.avatar.url(:news_images), :class => 'work-sample') %>
<% end %>
</div>
<p class="post-description"><%= #tynewyddpost.comments.html_safe %></p>
<div class="post-item-panel">
<ul>
<li class="date">
<p><%= date_output(#tynewyddpost.published_on) %></p>
</li>
</ul>
</div>
</div>
Controller
def tynewyddnews
tynewyddpost = Post.tynewydd_posts.find(params[:post_id])
tynewyddpost.shift
#tynewyddpost = tynewyddpost
#tynewyddpostlatest = Post.tynewydd_posts.first
end
tynewydd_posts is a scope
scope :tynewydd_posts, :include => :department, :conditions => {"departments.name" => "Ty Newydd"}, :order => "posts.published_on DESC"
So my issue at the moment is when i try and render the page i get the error
Couldn't find Post without an ID
Apologies for the long post but if someone could point me in the right direction that would be great
Thanks
It looks to me like you're doing it way wrong, sorry. It doesn't need to be that complicated. I would start over from scratch with a much simpler example, and then build up from there.
I would do something like rails g scaffold post title:string and then do this, just in a browser console:
$.ajax({
url: "/posts/index"
}).done(function() {
console.log("done");
});
You should be able to see the data coming back through your browser's console. On the Rails side, that data is coming from here:
class PostsController < ApplicationController
def index
#posts = Post.all
# there might be more stuff here
end
end
Hopefully you understand what I'm talking about. If you don't, I'd recommend separately learning a little more about Rails and a little more about jQuery/ajax before trying to combine the two.
OK so it seems my issue was the way i was calling the id of a post and I also moved my ajax call into a separate action, setup all be it complicated is correct.
What i changed
<%= link_to t.title, tynewyddnews_path(:type => 'tynewyddnews'), :post_id => t.id, :remote => true %>
was changed to
<%= link_to t.title, my_path_path(:type => 'tynewyddnews', :id => t.id), :remote => true %>
Controller
I added a new action to handle the ajax call, finding a post by id
def my_path
#tynewyddpost = Post.find(params[:id])
end
Then in my partial I could use the #tynewyddpost instance variable
Hope this helps someone else

Resources