Using link_to remote: true to pass parameters to rails - ajax

So I have a page with several messages, each with a link that changes (refines) the RATING of that message. When a user clicks on this link, I want an AJAX call that updates the corresponding column value in the database for that message. When this link is clicked, nothing should happen visibly. There should be no page refresh or reload.
I've been trying to do this using link_to remote: true, but I can't seem to get it to work. Documentation online is fairly unclear on this question and with the changes between Rails 2 and 3, some things like :with are no longer supported.
I've copied what I have so far, but I know its far from even coming close to a solution.
In terms of parameters I need passed into the database, I need the profile_id, the message_id and the new_rating.
Thanks in advance!
show.html.haml
.status-bar
= link_to "", { action: :refine_result }, remote: true
profile_controller.rb
...
def refine_result
#refinement = ResultRefinement.new
#refinement.profile_id = params[:profile_id]
#refinement.message_id = params[:message_id]
#refinement.save
respond_to do |format|
format.html { render nothing: true }
format.js { render nothing: true }
end
end
result_refinement.rb
class ResultRefinement < ActiveRecord::Base
attr_accessible :profile_id, :message_id, :new_rating, :deleted
belongs_to :profile
end

You need to set up a route for ProfileController#refine_result first. Something like
match '/profile/refine_results' => 'profile#refine_results', :as => 'refine_results'
Then you can use
.status-bar
= link_to "", refine_results_url(profile_id: 1, message_id: 100, new_rating: "awful"), remote: true

Related

Preview Post before save in active admin

I am looking for some pointers on getting started with this feature; I would like a user to be able to preview what their post would look like if saved
ActiveAdmin.register Post do
permit_params :comments, :title, :category_id, :slug, :published
# Create Blog Post
form do |f|
inputs 'Blog' do
f.semantic_errors
f.input :title
f.input :category_id, as: :select, collection: Category.all
f.input :comments, as: :text, input_html: { rows: 10, cols: 10 }
f.input :published, as: :boolean
end
inputs 'Submit' do
f.actions
end
end
end
So looking at the active admin documentation I can see you can add custom action items
action_item :preview, only: :new, name: 'preview_button' do
# do stuff here
end
I can also add a custom controller action in the form of a collection_action which will also add a route for me
collection_action :preview, method: :post do
#post = Post.new(params[:post])
end
So now I have a custom action preview and a button that can pass data to the method (I have hard coded it for now, as unsure how to get the data from outside the form).
This is what I have so far:
action_item :preview, only: :new, name: 'preview_button' do
link_to 'Preview', preview_my_admin_panel_posts_path(post: { title: 'Test Title', comments: 'test comments', category_id: '1' })
end
# Add controller action
collection_action :preview, method: :get do
#post = Post.new(params[:post_params])
end
My view gets rendered but nothing gets outputted, how do I then show the data?
Is this the correct approach?
Update
Can now show the hardcoded data with
collection_action :preview, method: :get do
#post = Post.new(permitted_params[:post])
end
The difference being in the active admin docs
The permit_params call creates a method called permitted_params. You should use this method when overriding create or update actions:
Now I just need to grab the form data outside the form and pass it through my link_to and then be able to keep the form populated with the same data if I go back to the form.
Ideally I would like to have the preview button within the f.actions as then I would have access to the #post object.

Rails3 association and accepts_nested_attributes_for failing when validation of user_id on

I am following the Rails Tutorial doing a little project for myself and then try to progress.
Well I am facing a problem for which I found the solution, but I'll really appreciate any thoughts and opinions because to make it work I have to disable a validation in an association.
The context is as follow : the application (big name for what it does actually...) has users to track their weight. I would like that when a user sign up, he/she enters a first measure on the go.
So here are the simplified models:
User.rb
class User < ActiveRecord::Base
attr_accessible :email, :name, :password, :password_confirmation, :measures_attributes
has_secure_password
has_many :measures, dependent: :destroy
accepts_nested_attributes_for :measures
# here goes validations before_save, etc. taken from the Rails Tutorial
end
Measure.rb
class Measure < ActiveRecord::Base
attr_accessible :weight
belongs_to :user
# This is kind where the problem is...
# If I deactivate the validation for user_id everyhing goes fine
validates :user_id, presence: true
validates :weight, presence: true, numericality: { greater_than: 0 }
default_scope order: 'measures.created_at ASC'
end
Here is the Users controller
class UsersController < ApplicationController
# GET /users/new
def new
#user = User.new
#user.measures.build
end
# POST /users
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Hi #{#user.name}. Welcome !"
redirect_to #user
else
render :new
end
end
end
Here is the form partial for the user :
<%= form_for(user) do |user_form| %>
<%= render 'shared/error_messages', object: user_form.object %>
<%= render 'users/fields', user_builder: user_form %>
<%= user_form.fields_for :measures do |measure_fields| %>
<%= render 'measures/fields', measure_builder: measure_fields, full: true %>
<% end %>
<%= user_form.submit submit_text, class: 'btn btn-large btn-primary' %>
<% end %>
And even when I fill the form correctly, I get this error :
* Measures user can't be blank
The only way I found to make it work is to get rid of the :user_id validation for presence in the Measure model. I want to emphasize that when this validation is off, the user is saved, the measure is saved and correctly associated with the newly created user.
Am I doing something wrong ? Is the :user_id presence validation in the Measure model really useful (it is in the Rails Tutorial and it makes perfectly sense for me) ? If yes why is the Measure validation failing when it is on ?
Thanks a lot in advance.
You could try validates :user instead of user_id. Then it might work out that the two are associated in memory even though the User hasn't been saved yet.
I think I may have found an error in your code that would cause the error you're seeing.
In your new controller you specifically create an association:
#user.measures.build
In your create controller, you create a new element based on the fields that were passed in.
#user = User.new(params[:user])
There are some cases where the associated element will be dropped. I can't remember if this happens by default if it doesn't validate or if there was an option you need to set to make it drop.
I think you may need to add
#user.measure.build if #user.measures.empty?
in your create controller else clause before render :new.
I don't know if you're actually hitting this problem, but it would explain why the association to your User wasn't set.

How to setup a rails 3 route for a nested resource and custom controller action

I have a recommendation that is nested below Categories and Awards.
So Category/:id/awards/:id/recommendations/:id
I have an Assets model that handles paperclip attachments to the Recommendation. A Recommendation has_many Assets, Assets belong_to :recommendation
In my Recommendation new/edit views I am rendering a form partial (as is normal) that gives the user the option to upload several assets.
If there are Assets already related, then it lists them. I am working on setting up a custom delete action on the recommendations controller.
My current link_to:
<%= link_to "Delete Attachment",
{:controller => :recommendations, :action => :destroy_asset, :id => asset.id },
{:remote => "true", :confirm => "Are you sure you want to delete this image?"}
%>
My Controller action:
def destroy_asset
##recommendation = Recommendation.find(params[:id])
#asset = Asset.find(params[:id])
#asset.destroy
respond_to do |format|
format.js
end
end
routes:
resources :recommendations
resources :categories do
resources :awards do
resources :recommendations
end
end
I am still learning remote => true, and how to route this sucker. Not sure if I need to have the route nested or not. I tend to think not. Since I have an Asset.id in my loop, I should just be able to execute the destroy without needing the Recommendation at all.
So the question/s: do I need a route to access a custom action in my recommendations_controller?
thanks
Try this:
resources :categories do
resources :awards do
resources :recommendations
member do
get :destroy_asset
end
end
end
end
Or If you only want only destroy_asset action under recommendation controller, do something like this :
resources :recommendations
member do
get :destroy_asset
end
end
Or If you want custom match, do something like this :
match "asset/:id/destroy_asset", :to => "recommendations#destroy_asset",
:as=> "destroy_asset"

Rendering ajax result in different view Rails 3

Given that I have the routes.
root :to => 'pessoas#index'
post '/pessoas' => 'pessoas#create'
And my view app/view/pessoas/index.haml has the following view code. (Submit here will post to pessoas#create)
= form_tag "/pessoas", :method => :post, :remote => true, :id => "participe" do
...
= button_tag "Sign up", :class => "envia"
And my create.js.erb view is.
$('#user-feedback').html('<%= #message %>');
And the controller code simply saves the model.
def create
#pessoa = Pessoa.new(params[:cliente])
if #pessoa.save
#message = "Success"
else
#message = "Failure"
end
respond_to do |format|
format.js
end
end
Then I go to the root path /
And I fill the form and click on submit.
Then the element p#user-feedback haven't been changed. Why?
I notice in app's log: that the request was done right and the jquery also but it render at /pessoas response but not at current view (index).
What can I do? Or should I just forget about this and make this with $.ajax way?
I want a way to provide feedback to the users.

Updating (Hiding) a group of objects in Rails 3

I've some difficulty in determining any way to update my objects as a group. I have an Alert model which has some alerts for the user. I'd like to provide a way to update them in bulk, as I've noticed that I often want to. I just don't know Rails well enough to know what 'the Rails way' would be.
My controller:
class AlertsController < ApplicationController
def index
#alerts = Alert.all(show: true)
end
def destroy
alert = Alert.get(params[:id])
## I lied, I'm not really deleting things, just hiding them from showing
alert.update(show: false) if alert
respond_to do |format|
format.js { render :nothing => true }
end
end
I've been using this code in my *.html.haml view to create the delete link for each individual alert:
- #alerts.each do |alert|
%span{ :class => 'description' }=alert.description
= link_to "Destroy", alert, :confirm => "Are you sure", :method => :delete, :remote => :true
What I want to have is a link on my index page Delete All which I could use to hide(update) all of the alerts. I've been attempting this with a destroy_all method for my controller, but I felt like it wasn't quite the right approach, as I didn't know how to link to something like that. Thank you for pointing me in the right direction.
Here is the destroy_all method I'd hacked together, for reference.
def destroy_all
#alerts.each do |alert|
alert.update(show: false) if alert
respond_to do |format|
format.js {render :nothing => true}
end
end
end
I don't know how you have routed to this controller but I would probably do something like this:
#routes.rb
resources :alerts do
delete :remove_all, :on => :collection
end
This will create a route looking like /alerts/remove_all which can only be called through the DELETE protocol. By specifying :collection it tells the routing the this route is not a sub route to one specific Alert so no :id is included.
Then the controller action could probably look something like this:
def remove_all
Alert.update_all({ show: false }, { show: true })
respond_to do |format|
format.js {render :nothing => true}
end
end
The update_all function will make sure that there is only one database update instead of one for each alert that is to be removed. The first argument is a hash containing the updates and the second argument is a hash with the conditions for which records are to be updated.
And from the view you should be able to link to the action like this:
= link_to "Remove All", remove_all_alerts_path, :confirm => "Are you sure", :method => :delete, :remote => :true
remove_all_alerts_path is a path helper that is automatically generated when you use the above syntax in routes.rb

Resources