I'm trying to put a new form that creates new "Addicts" in a modal in my home page.
It's a simple form with 2 inputs, that when clicking on New, a modal pops up with that form in my index page.
I can't get it to work because it keeps saying "Couldnt find Addict without an ID".
My Pages Controller
class PagesController < ApplicationController
def home
#addict = Addict.find(params[:id])
#lanzaderas = Lanzadera.all
render 'index'
end
end
My Addict Controller
class AddictsController < ApplicationController
def index
#posts = Addict.all
end
def show
#addict = Addict.find(params[:id])
end
def new
#addict = Addict.new(params[:addict])
end
def create
#addict = Addict.new(params[:addict])
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
end
end
My form in my modal
<%= form_for #addict do |f| %>
<%= f.input :name %>
<%= f.input :surname %>
<%= f.input :postal %>
<%= f.submit %>
<% end %>
I know it has something to do with the variable / id not being passed correctly in my Controller, but it's an error I get lots of times and don't know why I happens.
Thanks!
In def home in your PagesController you have this code:
#addict = Addict.find(params[:id])
I suspect, that you don't have the id for 'addict' in your parameters, when you visit your home action.
Do you want to display one particular addict in your 'home' page? If not, you can remove this line.
Update:
Change this in your AddictsController:
def new
#addict = Addict.new
end
In the new action you only "prepare" a new addict object. Using the find method is not possible, since the record hasn't been created yet.
If you're using Rails 4 you also have to permit your parameters (for security reasons; more info here: Railsguides: Strong Parameters)
In your case you have to do 2 things:
First: add this at the bottom of your AddictsController:
private
def addict_params
params.require(:addict).permit(:name, :surname, :postal)
end
Second: use this method in your create action instead of params[:addict]:
def create
#addict = Addict.new(addict_params)
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
Related
I currently have a basic controller and model that creates a Subscriber with the normal attributes(name, email, phone, etc...), but I also have a visit attribute on the Subscriber. So I have a form that's rendered with the "new" action and save the input with the create action. << VERY BASIC >> The new feature I want to implement is create a new form that takes in only a phone_number and when the number is entered it update the visit attribute on the subscriber that that corresponds with that number. right now I'm struggling trying to figure this out with just one controller. I'll show my current controller and hopefully that will help for clarity.
CONTROLLER
class SubscribersController < ApplicationController
def index
#subscriber = Subscriber.all
end
def new
#subscriber = Subscriber.new
end
def create
#subscriber = Subscriber.create(subscriber_params)
if #subscriber.save
flash[:success] = "Subscriber Has Been successfully Created"
redirect_to new_subscriber_path(:subscriber)
else
render "new"
end
end
def visit
#subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if #subscriber
#subscriber.visit += 1
#subscriber.save
redirect_to subscribers_visits_new_path(:subscriber)
else
render "new"
end
end
end
As you can see in the visit action I'm trying to implement this feature but I'm not sure where to go from here?
I suppose your search page has a form where you type the number you want to search for. And the request comes to visit action, where you'll increment the +1 to the visit count and then show the details of the number(subscriber).
def visit
#Comes request from search action
#subscriber = Subscriber.find_by_phone_number(params[:phone_number])
if #subscriber
#subscriber.visit += 1
#subscriber.save
redirect_to subscriber_path(#subscriber)
#It will show the details
else
flash[:alert] = "Didn't find with that number. Search again."
render :action => :search
end
end
Update:
Search logic
def search
#will render search.html.erb by convention
end
Inside search.html.erb
<%= form_tag({controller: "subscribers", action: "visit"}, method: "get") do %>
<%= text_field_tag :phone_number %>
<%= submit_tag "Submit" %>
<% end %>
So this will send params to visit action, and after incrementing it will render show method. Hope this helps. Let me know if there is anything.
We have an error in our erb files and the screen shot is here
We have everything in games.html.erb as below
<h1>Games#game</h1>
<%= form_for(#game) do |f| %>
<div class="game-field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= submit_tag "Game Created", :class=> "btn" %>
</div>
<% end %>
and here is the controller
class GamesController < ApplicationController
before_filter :store_location, :only => [:index, :show]
before_filter :require_user, :only => :show
before_filter :assign_game, :only => [:show, :destroy]
def index
#game = Game.new
end
def new
#game = Game.new
end
#game.add_player_from_user(current_user)
respond_to do |format|
format.html
format.json do render :json => {
:shouldStartNewRound => #game.is_ready_for_new_round?,
:shouldPassCards => #game.is_ready_to_pass?,
:isStartingFirstRound => #game.rounds.empty?,
:shouldReloadWaitAutoPlay => #game.should_reload?(current_player),
:shouldReloadAndJustWait => #game.should_reload_and_wait?(current_player)
}
end
end
end
def create
#game = Game.new(params[:game])
api_key = ""
api_secret = ""
#openTok = OpenTok::OpenTokSDK.new api_key, api_secret
session = #openTok.create_session request.remote_addr
#game.update_attributes(:session_id => session.session_id)
name = game[:name] # input from html
#game[:name] = name # setting input into db object (model)
if #game.save
redirect_to #game, alert: "game created"
else
render action: 'new'
end
end
def destory
#game.destory
redirect_to games_url
end
def reload
reload_partial
end
end
We are trying to create a deuces card game and we have bee stuck on that single problem. I have also looked for other similar problem that people have asked and we were not able to find the issue, it says that we have to put .new function to initialize the data. But the error is still showing up. Please help us!
You don't have a #game method in your GameController class.
Rename your #index action into #game or your View file.
I don't know how your routes file looks like but I suppose that the index action is the action that you call if somebody calls the root route, so http://localhost:3000/. If that's right then you have to rename game.html.erb into index.html.erb.
It looks like you are calling the action #game on controller Games. There is no #game method defined on the controller, so the instance variable #game never gets defined like it does in #index or #new. You can create a #game method in the controller and define #game in that method as needed.
Also, you have some code in the controller that needs to be inside of a method, starting at #game.add_player_from_user(current_user). Right now it's just executing at load time and probably not doing anything that makes any sense.
Finally, I noticed that you misspelled 'destroy' in a couple of places - search for 'destory' and replace with 'destroy' to avoid problems later.
The problem in brief: I'm working on a rails 4 app (4.1.8) and I'm trying to get flash[:notice] and flash[:alert] to show up under a form.
Two controllers: landingpage_controller and contacts_controller. The landingpage_controller serves a static landingpage through its show action and the contacts_controller has new and create actions, to store the contacts in a db table.
On the static landingpage, a modal with id="contact-modal" contains a partial with a simple_form_for #contact (see below). Upon submittal of the form, a db-entry is not created if the fields are not all filled out and a db-entry is created if the fields are filled out. However, no flash messages are displayed.
Wanted output:
Ideally the partial would re-load without leaving/closing the modal, with either: a success message and an empty form or a alert message and the form as it was upon submittal. How do I do this?
The controller: app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
render layout: "contact"
end
def create
#contact = Contact.new
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
private
def contact_params
params.require(:contact).permit(:email, :structure, :message_content)
end
end
The form: app/views/contacts/_new.html.haml
= simple_form_for #contact, html: { id: "contact-form"} do |c|
= c.input :email
= c.input :structure
= c.input :message_content
= c.button :submit
.messages-container
= if flash[:notice]
%p
= flash[:notice]
= if flash[:alert]
%p
= flash[:alert]
Routes:
resources :contacts, only: [:new, :create]
I'm aware that a partial reload probably involves AJAX. I've read several StackOverflow questions on this but have not been able to figure it out. See here, here and these two blog-posts: jetthoughts, ericlondon.
Your help is very much appreciated
There are several problems in your code:
views, that start with underscore are called partials and are not full actions, but just parts of reusable view code (you don't redirect to them, instead you use render since you usually don't want a full page reload.
1.1 Rename your _new.html.haml to _form.html.haml
2.1 Create a new view new.html.erb(I guess you have that already, otherwise your new action might not work properly) with content = render 'form'
From what I understand you don't want the modal to close, just to render a form after successful submission or if there is an error.
In that case:
1.create a create.js.erb file in your views/contacts folder
create.js.erb
$("#your_modal_id").html("<%= j( render 'form') %>")
2. change your create action
def create
#contact = Contact.new(contact_params)
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
to your form add remote: true
WARNING: This will leave your form filled in even if it is successful.
More about this topic see:
http://guides.rubyonrails.org/v4.1.8/working_with_javascript_in_rails.html#form-for
Hope it helps, and I hope I didn't forget anything
Probably a very simple problem I'm overlooking. I'm building a feature similar to Facebook's "home" page for logged in users. A user can post topics in one form, and that form works perfectly.
There is a comment form under each posted topic. When a user enters a comment and clicks the submit button the comment is created, but it is not shown unless I manually refresh the page. I can't see what I'm doing wrong here.
_form.html.haml
= form_for [topic, Comment.new], remote: true do |f|
.form-group
= f.text_area :body, rows: 2, class: 'form-control', placeholder: "Make a comment"
= f.submit "Post", class: 'f-button primary f-fw-bold post-btn'
I have tried using #topic for this form as well but get the error: undefined method `comments_path'
comments_controller.rb
class CommentsController < ApplicationController
def create
puts "TOPICS PARAMS",params[:topic_id]
#topic = Topic.find(params[:topic_id])
#comments = #topic.comments
#comment = current_user.comments.build( comment_params )
#comment.topic = #topic
#new_comment = Comment.new
if #comment.save
flash[:notice] = "Comment was created."
redirect_to topics_path
else
flash[:error] = "There was an error saving the comment. Please try again."
redirect_to topics_path
end
end
private
def comment_params
params.require(:comment).permit(:body, :topic_id)
end
end
All of this is rendered in the topics#index path, so here is the topics controller as well.
topics_controller.rb
class TopicsController < ApplicationController
def index
#topics = Topic.order(created_at: :desc)
#comments = Comment.all
#limited_partners = LimitedPartner.all
#users = User.all
#comment = Comment.new
end
def show
#topic = Topic.find(params[:id])
end
def create
#topic = Topic.new(topic_params)
#topic.user_id = current_user.id if current_user
#topic.limited_partner_id = current_user.limited_partner_id if current_user
if #topic.save
flash[:notice] = "Topic was saved successfully."
redirect_to topics_path
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def new
end
def edit
end
def update
end
private
def topic_params
params.require(:topic).permit(:body, :liked, :limited_partner_id, :user_id, :comment_id)
end
end
In the index.html.haml file I call the partial like this:
= render partial: 'comments/form', locals: { topic: topic, comment: #comment}
You are using remote: true for your form. So the submit will trigger an Ajax request. A javascript response will be returned, but no HTML will be updated by default.
You will need to sprinkle some javascript to update the HTML yourself: bind a callback to the ajax:success event, or use a js view (e.g. app/views/comments/create.js.erb).
Have also a look at Turbolinks 3 (still in development), which can reduce the amount of custom javascript required for partial page updates.
Your problem likely lies here ...
= form_for [topic, Comment.new], remote: true do |f|
Try this instead
= form_for #new_comment, url: {controller: 'comments', action: 'create'}, method: "post", remote: true do
and be sure your config/routes.rb looks something like this
get "/some-path", to: "comments#create"
post "/some-path", to: "comments#create"
I had to use javascript to get better control over the form and data. So I made a topic.coffee file with this:
$ ->
$('.new_comment').on 'submit', (event) =>
form = $(event.target).closest('form')
topicCommentsId = form.attr('action').replace(/\//g, '_').substring(1)
owningCommentsSection = $('#' + topicCommentsId)
formData = form.serialize()
$.post form.attr('action'), formData, (data) =>
extractedBody = $(data.substring(data.indexOf('<body')))
topicComments = extractedBody.find('#' + topicCommentsId)
owningCommentsSection.html(topicComments.html())
form.find('[name="comment[body]"]').val('')
location.reload();
return false
I removed the remote: true from my form as well and identify each topic in my index.html.haml with this:
.f-grid-row.topic_comments{id: "topics_#{topic.id}_comments"}
- topic.comments.each do |comment|
- if comment.topic_id == topic.id || comment.post_id == topic.id
...
Trying to update 2 attributes to a User model, this is my current code in the Users controller:
def update
#user = User.find(params[:id])
if #user.update_attributes(songkickID: params[:user][:songkickID], jamID: params[:user][:jamID])
redirect_to #user
else
redirect_to #user
end
end
The Songkick ID and the Jam ID are entered into 2 different fields. However, with the current code, if I attempt to update the Jam ID on its own, it updates that attribute, but then redirects to the user page (as expected), where the Songkick ID is now nil. Upon entering the Songkick ID again, the Jam ID becomes nil. I suppose this is because they are both part of the same if statement in the controller?
I attempted to use an elsif for the jamID params, but it does not seem to recognise at all (i.e. won't update that attribute for the user). Also attempted || conditional operator.
EDIT: Here's the 2 different forms:
<%= form_for(#user) do |f| %>
<%= f.text_field :jamID, :id=>"jamURL" %>
<%= f.submit "Jam ID", :onclick => "changeImg()", id: "saveJam" %>
<% end %>
and
<%= form_for(#user) do |f| %>
<%= f.text_field :songkickID %>
<%= f.submit "Songkick ID", :type => :image, :src => image_path("songkicklogo.png"), id: "skLogo" %>
<% end %>
And I tried modifiying the code to update_column, but I get wrong number of arguments (1 for 2).
EDIT 2: Following layout from Hartl's Rails Tutorial, I attempted this to define strong parameters:
private
def user_params
params.require(:user).permit(:songkickID, :jamID)
end
But I still get the Forbidden Attributes Error?
EDIT 3: The following code passes, but I worry it doesn't adhere to Rails 4 strong parameters:
Controller:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def edit
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:songkickID, :jamID)
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to #user
else
redirect_to #user
end
end
end
If I move update to below the update method, I get an undefined variable/method error for user_params, and I cannot make it private.
So - why are you explicitly naming the attributes in your update_attributes?
You should be able to use the following:
#user.update_attributes(params[:user])
Remember that if you've named your form fields correctly, params[:user] is a hash that will already have the keys you want (:songkickID etc)
Now - you will get one of two things coming through to your action, which you then pass through to update_attributes as:
{:songkickID => someID}
{:jamID => someOtherID}
which will correctly update your user and only change the one that is passed.
The problem with your earlier code was that what you passed to update attribute was:
{:songkickID => someID, :jamID => nil}
{:songkickID => nil, :jamID => someOtherID}
which was deliberately overwriting the other id with the nil you passed.
EDIT from OP: Thanks for this, and here's my final controller code:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to #user
else
redirect_to #user
end
end
private
def user_params
params.require(:user).permit(:songkickID, :jamID)
end
end
In last case scenario:
def update
if params[:user][:songkickID]
received_param = { songkickID: params[:user][:songkickID] }
elsif params[:user][:jamID]
received_param = { jamID: params[:user][:jamID] }
end
#user.update_attributes(received_param)
redirect_to #user
end
Note: I removed the last condition since it wasn't useful