I have a big problem with checkboxes and boolean values. I want to simply change value of one field in db using checkbox. Code is like this:
Collection_controller:
def update
#collection = Collection.find(params[:id]).album
if #collection.update_attributes(:for_sale)
flash[:success] = "success"
redirect_to current_user
else
flash[:success] = "not working"
end
end
def collection_params
params.require(:collection).permit(:to_buy, :for_sale)
end
and form:
<%= form_for collection do |f| %>
<div><%= f.check_box :for_sale%></div>
<%= f.submit "sale", class: "btn btn-primary" %>
<% end %>
Is there anyone who know why it is not working?
EDIT
One important fact, after clicking 'submit' I have flash message 'success'. So why I dont see the changes? It is problem in controller, or somewhere else?
First of all this should be hash of parameters.
http://apidock.com/rails/ActiveRecord/Base/update_attributes
You need to pass in what you want to update. Possibly like so:
if #collection.update_attributes(collection_params)
But it looks like you're incorrectly setting your collection variable to be the album of the collection, so fix that too
#collection = Collection.find(params[:id]).album
should be
#collection = Collection.find(params[:id])
Related
There are 2 forms on one page. I want an if else statement in the controller to use different params and variable values depending on which form was submitted. From doing a google search the best I came across was to have a value on the submit button.
<%= f.submit "Save" :value => "x" %>
If this is a plausible way I cant find how to make an if else statement for checking if the submit value is 'x'.
Something like
if submit.value == 'x'
do something
else
do something else
end
Really not sure. If there is another way of having an if else statement in the controller to catch witch form was submitted by using an id or name or whatever I'm happy to hear it.
The value of the submit button can be accessed with the help of params[:commit], so you can use it to check which form is submitted.
if params[:commit] == 'x'
do something
else
do something else
end
#Pavan has the direct answer, however if you're evaluating form submissions by their respective submit values, you've got a major issue with your pattern.
Form
Forms should be a way to pass values to your controller, which will then populate the model. You should not have to determine actions based on those values, unless you have different functionality...
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= form_for post do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
<% end %>
The above will create multiple forms, all submitting to the posts#update method:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update
#post = Post.find params[:id]
#post.update post_params
end
private
def post_params
params.require(:post).permit(:x, :y, :z)
end
end
The values inside those forms don't matter, nor to which post object they were sent; they will all be evaluated in exactly the same way.
--
Actions
The other way around this is to make separate actions for the different forms:
#config/routes.rb
resources :posts do
patch :update_2, on: :member
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def update_2
#post = Post.find params[:id]
#post.param = "value"
#post.update post_params
end
end
#app/views/posts/show.html.erb
<%= form_for #post, url: posts_update_2_path(#post) do |f| %>
<%= f.submit %>
<% end %>
You could use something like
<%=f.submit "Basic update", name: "basic-update" %>
<%=f.submit "Security update", name: "security-update" %>
and then check in your controller:
if params.has_key? "security-update"
#do something
elsif params.has_key? "basic-update"
#do another thing
end
My form gets passed a 'new' Quiz (not saved to the database). My form partial looks like this:
<%= form_for(#quiz) do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%= f.check_box(:answer2) %>
<%= f.check_box(:answer3) %>
<%= f.check_box(:answer4) %>
<%= f.check_box(:answer5) %>
<%= f.check_box(:answer6) %>
<%= f.check_box(:answer7) %>
<%= f.check_box(:answer8) %>
</p>
<p>
<%= f.submit("Get my results!") %>
</p>
<% end %>
Here is my QuizzesController#create action:
def create
#results = Quiz.create(post_params) #from private method
if #results.save
redirect_to results_path
else
#error handle here
end
end
...which gets triggered when the user clicks 'get my results' on my quiz form. And the post_params method looks like this:
def post_params
params.require(:quiz).permit(:id, :user_id, :answer1, :answer2, :answer3, :answer4, :answer5, :answer6, :answer7, :answer8) #add other attributes here
end
My results/index.html.erb looks like this:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<h1>Results</h1>
<p><%= #results.inspect %></p>
</div>
</div>
But that 'inspected' Quiz instance returns 'nil' for all the answers1, answers2 etc attributes. Any idea why that would be? Is there something I'm NOT doing to save the user's answers to the database?
The reason it shows nil is because you are not setting the variable.
After creating and saving, you redirect to results_path and the variable #results does not persist during a redirect. Without seeing the full code, I'll have to guess at your naming conventions but there are two ways to do this.
1) If you want to redirect to the index then in the code for your index action, you can set the variable:
#results = Quiz.last
This is easy to work with in development because you are the only user and this will always return the last quiz you created. Not so great in production.
2) The alternative is to redirect to the show action for that quiz.
def create
#results = Quiz.new(post_params)
if #results.save
redirect_to result_path(#results)
else
# error handle here
end
end
Again, I have had to guess that result_path is the correct path. Without seeing the full routes file, I cannot be sure but you can rename accordingly if necessary.
Basically I have a follow button and when click the page refreshes and I show an unfollow button in place. Below is the code I use to render the particular form needed:
follow_forms partial:
<% unless current_user?(#user) %>
<% if current_user.following?(#user) %>
<%= render 'relationships/partials/unfollow' %>
<% else %>
<%= render 'relationships/partials/follow' %>
<% end %>
<% end %>
Any I changed the form to an ajax form because I don't want the page refresh and on success of the form submission I'd like to replace the follow button/form with an unfollow button/form. This isn't straight forward because only 1 form shows at a time so I can't use my jquery selector to find this form anyway.
What I decided to do was create a new action that renders the follow_form partial this way the appropriate form will be available for me to manipulate with my jquery selector.
The new action:
class RelationshipsController < ApplicationController
def get_follow_form
respond_to do |format|
format.html { render :partial => 'relationships/partials/follow_form_ajax' }
end
end
end
The problem now is that I don't have access to the #user instance variable. That doesn't matter to much because I can get the user who was just followed via the jquery success data then pass that as data in the new ajax call to get_follow_form_url and then pass that info into the partial as a local variable.
I still have an issue with the #user instance variable not being available. Which brings me to my question.
How can I make another value be used if the instance variable isn't nil/doesn't exist?
The form for following:
<%= form_for current_user.relationships.build(:followed_id => #user.id), :remote => true do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit "Follow", :class => 'followButton' %>
<% end %>
Can I do something like this
:followed_id => #user.id <-if this doesn't exist use this-> user.id
There are other ways around this like creating new partials that are only used for this whole situation or creating some messy if statements but I feel like creating duplicate forms should be my very very very last option.
I look forward to you solutions thanks
Kind regards
There's a very simple way to do this, assuming you have your 'fallback' ID:
:followed_id => #user.present? ? #user.id : fallback_id
Use something like the andand gem or just try and a logic expression:
:followed_id => #user.andand.id || user.id
Even without that you can use identical logic, and certainly don't need multiple partials:
:followed_id => (#user && #user.id) || user.id
But as Frederick says, if you have a replacement value for the object already, couldn't you just set it?
I have an action like this:
def add_credit_card
if request.post?
unless params[:conditions]
flash[:error] = 'You need to accept!'
end
end
end
This action renders the following view:
<%= form_tag do %>
<fieldset>
<%= check_box_tag "conditions"%> I agree to the <%= link_to "Terms and Conditions", consumer_terms_and_conditions_url, :target => "_blank" %>
</fieldset>
<%= submit_tag "Submit" %>
<% end %>
When I do a GET to that action no errors are shown. When I do a submit with that box checked no errors are shown. When I do the first submit without that box checked the error is shown, but the problem comes when I do another submit and the checkbox is not checked, the errors are still there.
My questions are:
Why is that happening?
What would be a better approach to deal with this situation, where a form is not attached to a model and the errors have to be shown just when the user has submitted the form?
Since you're using the same action, you'll want to use flash.now so the flash hash does not persist to the next action.
flash.now[:error] = 'You need to accept!'
Also, it's not essential, but consider using:
<%= check_box_tag 'conditions', 'accepted' %>
and then checking the value of the params[:conditions] for the string "accepted" i.e.:
unless params[:conditions]=='accepted'
flash.now[:error] = 'You need to accept!'
end
I have a model, Product, and on the show view for this model, I want to have a select box for the user to be able to view a different Product. So, if a user's looking at the "Product 1" page, they can select "Product 2" from the select box and view that product.
Here's the code I'm using to create this select box:
<%= form_tag({:controller => "products", :action => "show"}, :method => :get) do %>
<%= select_tag :product_id, options_from_collection_for_select(Product.all, :id, :title) %>
<%= submit_tag 'Go' %>
But this doesn't work. I can choose a different product, and click Go, but it just goes to the same product, not the one I selected in the box.
What am I doing wrong here?
Basically, I'm trying to use a select box instead of something like this:
<% Product.all.each do |p| %>
<%= link_to p.title, p %>
<% end %>
Here's what I have for my show action in the controller:
#product = Product.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:alert] = 'The product you were looking for could not be found'
redirect_to products_path
well a simple way would be to check if the params[:product_id] was passed by your form, if it is then use that instead of params[:id] basically:
if params[:product_id]
#product = Product.find(params[:product_id])
else
#product = Product.find(params[:id])
end
If you can post your code on the ProductsController for Show, it would clarify things more.
The id you want to use for "showing" the right product is passed by params[:product_id]. So you should be using that in your ProductsController