Rails - JavaScript view not updating page correctly after Ajax request - ajax

I have Questions, which can be voted on. When I list each question on the question's index, I put the "yes" vote and "no" vote buttons alongside each one. I am trying to use Ajax to create votes and render a js view that updates the vote counts.
I'm observing this behavior:
The votes are successfully created and saved. The first "yes" vote made on each question adjusts the count correctly for that question, but creating any "yes" votes after that will not update the count despite the vote objects being saved. The "no" buttons never update the label correctly. Randomly, clicking on a "No" button will increase that question's no_vote count to 80. If I refresh the page, all the counts update to the correct value as expected.
question.rb
class Question < ActiveRecord::Base
attr_accessible :body, :title, :pass_percentage
has_many :votes
has_many :yes_votes, class_name: 'Vote', conditions: { is_yes: true }
has_many :no_votes, class_name: 'Vote', conditions: { is_yes: false }
...
end
vote.rb
class Vote < ActiveRecord::Base
attr_accessible :is_yes, :question_id
belongs_to :question
validates :is_yes, inclusion: { in: [true, false]}
validates :question_id, presence: true
end
views/questions/index.html.erb
...
<%= will_paginate #questions %>
<ul class="questions">
<% #questions.each do |question| %>
<li>
<section class="question_<%= question.id %> clearfix">
<h2><%= link_to question.title, question_path(question) %></h2>
<p><%= truncate(question.body, length: 70) %></p>
<div class="vote-buttons">
<%= render partial: 'shared/yes_vote',
locals: { question: question } %>
<%= render partial: 'shared/no_vote',
locals: { question: question } %>
</div>
</section>
</li>
<% end %>
</ul>
...
_yes_vote.html.erb
<div class="vote-btn yes-vote-btn">
<%= form_for question.votes.build(is_yes: true), remote: true do |f| %>
<%= f.hidden_field :is_yes %>
<%= f.hidden_field :question_id %>
<%= f.submit "Yes", class: "btn btn-large btn-success" %>
<% end %>
<span class="yes-votes-count"><%= question.yes_votes.count %></p>
</div>
_no_vote.html.erb
<div class="vote-btn no-vote-btn">
<%= form_for question.votes.build(is_yes: false), remote: true do |f| %>
<%= f.hidden_field :is_yes %>
<%= f.hidden_field :question_id %>
<%= f.submit "No", class: "btn btn-large btn-danger" %>
<% end %>
<span class="no-votes-count"><%= question.no_votes.count %></span>
</div>
votes_controller.rb
class VotesController < ApplicationController
def new
#vote = Vote.new
end
def create
#vote = Vote.new(params[:vote])
#question = #vote.question
respond_to do |format|
if #vote.save
format.html { redirect_to :back }
format.js
else
format.html { redirect_to :back, flash: { error: "There was an error" } }
format.js
end
end
end
end
questions_controller.rb
class QuestionsController < ApplicationController
def index
#questions = Question.paginate(page: params[:page])
end
...
end
views/vote/create.js.erb
$(".question_<%= #question.id %> .yes-votes-count").html("<%= #question.yes_votes.count %>")
$(".question_<%= #question.id %> .no-votes-count").html("<%= #question.no_votes.count %>")
Server Log:
Started POST "/votes" for 127.0.0.1 at 2013-05-17 02:53:38 -0400
Processing by VotesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"QD+7gj3G5r68B7cpxxW5ighB5M0Djluxx5XymnG4vog=", "vote"=>{"is_yes"=>"true", "question_id"=>"2"}, "commit"=>"Yes"}
Question Load (0.1ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = 2 LIMIT 1
(0.0ms) begin transaction
SQL (0.3ms) INSERT INTO "votes" ("created_at", "is_yes", "question_id", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["created_at", Fri, 17 May 2013 06:53:38 UTC +00:00], ["is_yes", true], ["question_id", 2], ["updated_at", Fri, 17 May 2013 06:53:38 UTC +00:00], ["user_id", nil]]
(0.1ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."question_id" = 2 AND "votes"."is_yes" = 't'
(0.0ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."question_id" = 2
Question Exists (0.0ms) SELECT 1 AS one FROM "questions" WHERE ("questions"."title" = 'Crust or no crust?' AND "questions"."id" != 2) LIMIT 1
(31.9ms) commit transaction
CACHE (0.0ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."question_id" = 2 AND "votes"."is_yes" = 't'
(0.1ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."question_id" = 2 AND "votes"."is_yes" = 'f'
Rendered votes/create.js.erb (1.2ms)
Completed 200 OK in 39ms (Views: 2.3ms | ActiveRecord: 32.6ms)
Sorry for the large amount of code. I tried to make it as clear as possible.
Why is this not working? Is there a much better way to get write create.js.erb view?

You wrote two #vote.save condition.Remove the first one and check again.
Must be validation problems as if you are saving same entry two times

Figure out my issue. The problem was in my create.js.erb. I needed to be using the .text() function not .html() to replace the contents of the element.
New code:
$(".question_<%= #question.id %> .yes-votes-count").text("<%= #question.yes_votes.count %>")
$(".question_<%= #question.id %> .no-votes-count").text("<%= #question.no_votes.count %>")
If anyone sees ways to improve my code in general though, post an answer and I'll accept it.

Related

Nested formed by cocoon cannot be saved

Problem
I'm coding user's profile page on Rails.
I added a gem "language-select" for users to choose a language which they're learning. And users might learn several languages, so I added gem "cocoon" as well.
The first language which users choose is successfully saved, but others which were chosen by cocoon cannot be saved. I would like them to be saved and being showed on their profile page.
How I reached this problem
I added cocoon by refering this page and code.README in github
However, "Save" button didn't react anything, so I made the form_for's method "post".
<%= form_for #user, method: :post do |f| %>
<div id='languages'>
<%= f.fields_for :languages do |language| %>
<%= render 'language_fields', :f => language %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add language', f, :languages %>
</div>
</div>
<% end %>
Then "Save" button worked, but an error occured.
ActionController::InvalidAuthenticityToken in UsersController#update
ActionController::InvalidAuthenticityToken
Extracted source (around line #211):
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
end
end
Therefore, I added "protect_from_forgery with: :null_session" to application_controller.rb. Then the error disappeared, but the problem which I mentioned above occered. The first language which users choose is saved, but other ones which were chosen by cocoon cannot be saved.
(users#show.html.erb)
<h2><%= #user.language %></h2>
(users#edit.html.erb)
<%= form_tag("/users/#{#user.id}/update", {multipart: true}) do %>
<table>
<p>Languages</p>
<%= select_tag(:language,options_for_select(languages)) %>
<%= render 'users/form' %>
<input type="submit" value="Submit">
</table>
<% end %>
(users#_form.html.erb)
Partial of cocoon.
<%= form_for #user, method: :post do |f| %>
<div id='languages'>
<%= f.fields_for :languages do |language| %>
<%= render 'language_fields', :f => language %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add language', f, :languages %>
</div>
</div>
<% end %>
(users#_language.html.erb)
Partial of cocoon.
<div class='nested-fields'>
<div class="field">
<%= select_tag(:language,options_for_select(languages)) %>
</div>
<%= link_to_remove_association "remove language", f %>
</div>
(users_controller.rb)
Even though I settled "redirect_to("/users/#{#user.id}")" here, it redirects to "/posts/index" after press "Save" button. And the sentence "You're already logged in" which I settled at "forbid_login_user" in "application_controller.rb" is shown too.
before_action :authenticate_user, {only: [:index, :show, :edit, :update]}
before_action :forbid_login_user, {only: [:new, :create, :login_form, :login]}
before_action :ensure_correct_user, {only: [:edit, :update]}
def edit
#user = User.find_by(id: params[:id])
end
def user_params
params.require(:user).permit(:name, :description, languages_attributes: [:id, :description, :done, :_destroy])
end
def update
#user = User.find_by(id: params[:id])
#user.language = params[:language]
if params[:image]
#user.image_name = "#{#user.id}.jpg"
image = params[:image]
File.binwrite("public/user_images/#{#user.image_name}", image.read)
end
if params[:cover_image]
#user.cover_image_name = "#{#user.id}_cover.jpg"
cover_image = params[:cover_image]
File.binwrite("public/user_cover_images/#{#user.cover_image_name}", cover_image.read)
end
if #user.save
flash[:notice] = "Edited user's information"
redirect_to("/users/#{#user.id}")
else
render("users/edit")
end
end
(application_controller.rb)
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :set_current_user
def set_current_user
#current_user = User.find_by(id: session[:user_id])
end
def authenticate_user
if #current_user == nil
flash[:notice] = "You need to log in"
redirect_to("/login")
end
end
def forbid_login_user
if #current_user
flash[:notice] = "You're already logged in"
redirect_to("/posts/index")
end
end
end
I will add more code if it needs to be refered. Thank you very much.
Version
ruby 2.6.4p104 / RubyGems 3.0.3 / Rails 5.2.3
Postscript
When I choose only one language, it can be saved.
When I choose like several languages like below, the problem which I mentoined above happens. Nothing is saved.
But after putting "skip_before_action :verify_authenticity_token" in application_controller.rb, only "English"(the last one) is saved (checked by rails console).
"Japanese" (chose by original form)
"English" (added and chose by cocoon)
Anyway, only 1 language can be saved so far.

Rails 5 - save rolls back because nested models parent model is not being saved before child model

Ok folks, Rails 5 has really had its nuances differing from Rails 4. What I have going on is that every time I click the submit button on the form it reloads with the error Profile user must exist and Profile user can't be blank. The form loads fine including the nested models form, but for what ever reason it is failing to save the parent model before attempting to save the child model with the following output to the console:
Puma starting in single mode...
* Version 3.7.0 (ruby 2.2.6-p396), codename: Snowy Sagebrush
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
Started POST "/users" for 192.168.0.31 at 2017-03-09 18:51:04 -0500
Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
ActiveRecord::SchemaMigration Load (0.2ms) SELECT `schema_migrations`.* FROM `schema_migrations`
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JPKO+ppAYqwWS8tWeXhEtbUWynXREu9jYlF0KIlyPgUaabHSzjPZocSxCvr/WEm1r6wAQyT1CvA6hNkZWfPD3Q==", "user"=>{"username"=>"test", "password"=>"[FILTERED]", "user_type_id"=>"1", "profile_attributes"=>{"first_name"=>"123", "middle_name"=>"123", "last_name"=>"123", "email"=>"123#123.com", "phone_number"=>"1234567890", "cell_number"=>"1234567890"}}, "commit"=>"Create User"}
(0.1ms) BEGIN
(0.2ms) ROLLBACK
Rendering users/new.html.erb within layouts/application
Rendered users/_form.html.erb (112.5ms)
Rendered users/new.html.erb within layouts/application (118.7ms)
Completed 200 OK in 834ms (Views: 780.1ms | ActiveRecord: 2.2ms)
I have have had other problems out of this relationship and I am thinking that maybe I need to rebuild the project.
Here is all of the relevant code around this issue:
###############################################################################
### Users Model
###############################################################################
class User < ApplicationRecord
has_one :profile, inverse_of: :user
accepts_nested_attributes_for :profile, allow_destroy: true
end
###############################################################################
### Profile Model
###############################################################################
class Profile < ApplicationRecord
belongs_to :user, inverse_of: :profile
validates_presence_of :user
end
###############################################################################
### Users Controller
###############################################################################
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
#user.build_profile
end
# GET /users/new
def new
#user = User.new
#user.build_profile
end
# GET /users/1/edit
def edit
#user.build_profile
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :password, :user_type_id, profile_attributes: [:id, :user_id, :first_name, :middle_name, :last_name, :phone_number, :cell_number, :email])
end
end
###############################################################################
### Form View
###############################################################################
<%= form_for(#user) do |f| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
<!--<li><%= debug f %></li>-->
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %>
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.text_field :password %>
</div>
<div class="field">
<% if params[:trainer] == "true" %>
<%= f.label :user_type_id %>
<%= f.text_field :user_type_id, :readonly => true, :value => '2' %>
<% else %>
<%= f.label :user_type_id %>
<%= f.text_field :user_type_id, :readonly => true, :value => '1' %>
<% end %>
</div>
<h2>Account Profile</h2>
<%= f.fields_for :profile do |profile| %>
<%#= profile.inspect %>
<div>
<%= profile.label :first_name %>
<%= profile.text_field :first_name %>
</div>
<div>
<%= profile.label :middle_name %>
<%= profile.text_field :middle_name %>
</div>
<div>
<%= profile.label :last_name %>
<%= profile.text_field :last_name %>
</div>
<div>
<%= profile.label :email %>
<%= profile.text_field :email %>
</div>
<div>
<%= profile.label :phone_number %>
<%= profile.telephone_field :phone_number %>
</div>
<div>
<%= profile.label :cell_phone %>
<%= profile.telephone_field :cell_number %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<%= debug params %>
<%= debug user %>
<%= debug user.profile %>
<% end %>
Alright I rephrased the question on another question and I finally found the answer to this. So I am pasting my answer from there, in case someone searches for the issue in the same fashion that I was asking the question here.
Ok, I am answering my own question because I know many people are struggling with this and I actually have the answer and not a vague response to the documentation.
First we will just be using a one to one relationship for this example. When you create your relationships you need to make sure that the parent model has the following
inverse_of:
autosave: true
accepts_nested_attributes_for :model, allow_destroy:true
Here is the Users model then I will explain,
class User < ApplicationRecord
has_one :profile, inverse_of: :user, autosave: true
accepts_nested_attributes_for :profile, allow_destroy: true
end
in Rails 5 you need inverse_of: because this tells Rails that there is a relationship through foreign key and that it needs to be set on the nested model when saving your form data. Now if you were to leave autosave: true off from the relationship line you are left with the user_id not saving to the profiles table and just the other columns, unless you have validations off and then it won't error out it will just save it without the user_id. What is going on here is autosave: true is making sure that the user record is saved first so that it has the user_id to store in the nested attributes for the profile model.
That is it in a nutshell why the user_id was not traversing to the child and it was rolling back rather than committing.
Also one last gotcha is there are some posts out there telling you in your controller for the edit route you should add #user.build_profile like I have in my post. DO NOT DO IT THEY ARE DEAD WRONG, after assessing the console output it results in
Started GET "/users/1/edit" for 192.168.0.31 at 2017-03-12 22:38:17 -0400
Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
Profile Load (0.5ms) SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 1 LIMIT 1
(0.1ms) BEGIN
SQL (0.5ms) UPDATE `profiles` SET `user_id` = NULL, `updated_at` = '2017-03-13 02:38:17' WHERE `profiles`.`id` = 1
(59.5ms) COMMIT
Rendering users/edit.html.erb within layouts/application
Rendered users/_form.html.erb (44.8ms)
Rendered users/edit.html.erb within layouts/application (50.2ms)
Completed 200 OK in 174ms (Views: 98.6ms | ActiveRecord: 61.1ms)
If you look it is rebuilding the profile from scratch and resetting the user_id to null for the record that matches the current user you are editing. So be very careful of this as I have seen tons of posts making this suggestion and it cost me DAYS of research to find a solution!
Rails 6.1
I had a similar issue that was fixed by removing validates_presence_of :user and validates :user_id, presence: true from my profile model. Your model obviously did not have the same validations mine had, but I thought it may be useful to add this answer in case others do.
I did not need to add inverse_of or autosave to either model to get the nested attributes to save correctly.
I came across this question because I had the same problem but only for my rspec tests. I ended up doing rails db:reset RAILS_ENV=test and that solved it. I did not need to add inverse_of: :user or autosave:true to the models.
One theory you could check in a dev or production system is if your seed for the table somehow got off. So then it can't insert the user row because the id is in use and then the profile create fails because the user create failed. In postgresql you could run: SELECT setval('users_id_seq', (SELECT max(id) FROM users}));
I was having a similar issue (did not save with nested attributes).
In the controller, I changed my #user.build_profile to #user.profile.build(params[:profile]) and it solved the issue.

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.

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

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.

Resources