How to pass javascript variable from Rails view to action - ruby-on-rails

I have a list of user emails in a bit of Javascript code in my view that I have created for my action. The view is in haml format.
I want to press a submit button on a form and access this list of emails in the same action or another action.
I've tried using form_tag, form_for and just normal html forms, however I keep running into different issues. I've also tested with link_to and button_to tags.
Here's what we have for the Action:
module RailsAdmin
module Config
module Actions
class BulkProperties < RailsAdmin::Config::Actions::Base
RailsAdmin::Config::Actions.register(self)
register_instance_option :collection do
true
end
register_instance_option :http_methods do
[:get, :put]
end
register_instance_option :controller do
proc do
#all_users = User.all
#all_properties = UserProperty.all
#all_roles = Role.all
binding.pry
if request.get? # EDIT
respond_to do |format|
format.html { render #action.template_name }
format.js { render #action.template_name, layout: false }
end
elsif request.put? # UPDATE
binding.pry #Just testing this
end
end
register_instance_option :link_icon do
'icon-lock'
end
end
end
end
end
And this the part of my view giving me issues:
%form
.multiselect-form
.wrapper{"data-children-count" => "1"}
%select.collection{:multiple => "multiple", :id => "multi"}
%hr/
%h1 List of user properties
-#all_properties.each do |prop|
%input{:name => prop.name+"checkbox", :type => "checkbox", :id => prop.name+"checkbox"}
#{prop.name}
%input{:name => prop.name, :type => "text", :id => prop.name}
%br
%input{:name => "submit", :type => "submit", :formaction => 'http://localhost:3000/admin/user/bulk_properties?Application=8&Company=1&locale=en', :method => 'put'}
%br/
%br/
The outcome is that I am led to a CanCan issue where I'm getting 'You are not authorized...'. This is because the url actually ends up holding the parameters and so it tries to redirect me to a webpage that doesn't exist.

I implemented an action that uploads a file with js to S3 and sets the value of a form field with javascript then i use that url on the rails admin action.
I'm pasting it all because in the past that would have helped me in these cases by comparing my approach to a working approach.
Here are the relevant (simplified)files:
# app/views/rails_admin/main/update_orders_and_line_items.html.haml
= form_tag(method: :post) do
= hidden_field_tag 'uploaded-file-url', '', id: 'uploaded-file-url'
= submit_tag 'Submit', class: 'action-button-pink'
# app/assets/javascripts/google_cloud_storage_field.js
let url = get_url(fileInput);
let valueField = $('#uploaded-file-url');
valueField.val(url);
# lib/rails_admin/config/actions/update_orders_and_line_items.rb
module RailsAdmin
module Config
module Actions
class UpdateOrdersAndLineItems < RailsAdmin::Config::Actions::Base
# Might cause random bugs if enabled
register_instance_option :pjax? do
false
end
register_instance_option :http_methods do
[:post, :get]
end
register_instance_option :controller do
proc do
if request.post?
url = params['uploaded-file-url']
do_stuff_with(url)
elsif request.get?
# [...]
end
end
end
end
end
end
end
I believe the source of your bug is using the %form tag, the default method of a form is GET and thats why your browser tries to redirect you to some page, if you use like i did form_tag(method: :post) and make sure the emails are on the hidden_field_tag value, you'll get your list on the action.rb

Related

How do I pass the select_tag's input to the rails controller

I'm trying to insert the input from a select_tag to my controller method.
I've looked and cannot seem to resolve the issue.
This is the code I have below, nothing for the rank's selection comes up in the params at all.
<h1>hello please set <%= #user.username %>'s rank'</h1>
<%= select_tag 'rank', options_for_select(#ranks.collect{ |r| [r.rank_name] }) %>
<%= button_to "Update", :action => "set_user_rank_update", value: "#{#user.id}", method: :post %>
Update below with the controller and routes
Controller:
class Admin::RankController < ApplicationController
before_action :admin?
def new
#rank = Rank.new
end
def create
#rank = Rank.new(rank_params)
if params["rank"]["admin"].to_i == 1
#rank.toggle! :admin?
end
if #rank.save
flash[:success] = "Rank created"
redirect_to root_path
else
flash[:danger] = "Failed to create rank"
render 'new'
end
end
def set_user_rank_new
#user = User.find_by_id(params["format"])
#ranks = Rank.all
end
def set_user_rank_update
#user = User.find_by_id(params["value"])
#rank = Rank.find_by_id(params["rank"])
#rank_backup = #user.rank.first
debugger
#user.rank - #user.rank.first
#user.rank << #rank
if #user.rank.first == #rank
flash[:success] = "Set user's rank"
redirect_to root_path
else
flash[:danger] = "Failed to set user's rank"
#user.rank - #user.rank.first
#user.rank << #rank_backup
render 'set_user_rank_new'
end
end
private
def rank_params
params.require(:rank).permit(:rank_name, :rank_color)
end
end
Routes
Rails.application.routes.draw do
devise_for :users,
:controllers => { :registrations => "member/registrations" , :sessions => "member/sessions"}
scope module: 'public' do
root 'welcome#index'
end
scope module: 'member' do
get 'members/:id' => 'member#show'
end
scope module: 'admin' do
get 'rank/new' => 'rank#new'
post 'rank/create' => 'rank#create'
get 'rank/set_user_rank/new' => 'rank#set_user_rank_new'
post 'rank/set_user_rank/update' => 'rank#set_user_rank_update'
end
end
Try passing 2 element arrays to options_for_select. The way you have it looks like it would get you option text but no values, which could explain why it doesn't show up in the params.
So for example:
<%= select_tag 'rank', options_for_select(#ranks.collect{ |r|[r.rank_name, r.id] }) %>
The button_to helper creates an inline form with just the parameters included in the helper statement (in this case the user id).
You can check this by examining the resulting HTML on your page - which I think will show an input field for rank sitting outside the form tag.
To include the rank parameter, you should set up the form using a form helper and make sure the rank input is included inside the form.
For what purpose do you need it in your controller action?
With the link_to you can forwards params as well.
It would be very helpful to see your controller and also your routes.

How to Pass or Refer to original controller instance variable? SOLUTION

I am trying to understand how to refer back to a controller's instance variable in calling a method in the same controller with rendered the view.
I basically instantiate an instance variable in the controller with a list of modems. In the view, I want to call an action to iterate over the instance variable array #modems and perform an action. My problem is that I don't seem to be able to either reference the #modems instance variable in the action called nor can I pass it from the view. If I try to pass the actual #modems back to the controller, I get a "connection reset" error page. And to reference the original instance variable fails. Haphazardly I tried to define/set #modem_cache in the application controller, then setting it equal to the #modems array in the getmodems method and then refer to it in the resetmodemcounters vs passing the instance variable back, did not work. I'm sure there some fundamentals that I'm overlooking, but not seeing them. I think I have included all the pertinent information. Please indicate if I need to provide additional. Any suggestions on what I'm doing wrong or how I might do it better I would greatly appreciate.
Thank you in Advance!
Controller app/controllers/cmts/cmts_controller.rb
def getmodems
# Array of modems and stats (NOT ActiveRecord)
#modems = Modems.all()
respond_to do |format|
format.html { render :modems, :layout => "application" }
end
end
# Called from modem.html.erb view
def resetmodemcounters
if (session[:admin])
params[:targets].each do |cm|
# do action
end
end
end
View app/views/cmts/modems.html.rb
....
<%= link_to image_tag('recycle-red-button.png', :height => '30', :width => '35'), resetmodemcounters_path(:targets => #modems), :confirm => 'Are you sure?', :method => :get %>
<% #modems.each do |cm| %>
<!-- Table of modem stats -->
<% end %>
....
Also tried this:
Controller app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
....
#sweep_cache = nil
....
end
Controller app/controllers/cmts/cmts_controller.rb
def getmodems
# Array of modems and stats (NOT ActiveRecord)
#modems = Modems.all()
#modems_cache = #modems
respond_to do |format|
format.html { render :modems, :layout => "application" }
end
end
def resetmodemcounters
log(params)
# {"_method"=>"get", "authenticity_token"=>"cZqSqAVKBpTiN5ZQSF1xUXMSiQmtDSQp8/6CRfis3Xs=", "target"=>"all", "controller"=>"cmts", "action"=>"resetmodemcounters"}
log(#modems_cache)
# nil
if (session[:admin])
if (params[:target] == 'all')
#modems_cache.each do |cm|
# do action
end
end
end
end
View app/views/cmts/modems.html.rb
....
<%= link_to image_tag('recycle-red-button.png', :height => '30', :width => '35'), resetmodemcounters_path(:targets => 'all'), :confirm => 'Are you sure?', :method => :get %>
<% #modems.each do |cm| %>
<!-- Table of modem stats -->
<% end %>
....
HERE'S WHAT I CAME UP WITH and works - Would there be a better way to handle this?
class ModemsCache
DATA = []
def update( modems )
DATA.replace modems
end
end
def getmodems
# Array of modems and stats (NOT ActiveRecord)
#modems = Modems.all()
# Update Cache
ModemsCache.new.update(#modems)
respond_to do |format|
format.html { render :modems, :layout => "application" }
end
end
def resetmodemcounters
if (session[:admin])
# Get Cached Data
modems = ModemsCache::DATA
modems.each do |cm|
# do action
end
end
end

No method error issue rails

I'm a new rails developer who has a basic scaffolded crud application that I modified a bit.
I'm getting this error:
undefined method description for #<ActiveRecord::Relation:0x00000102df26d8>
when I visit john/recipes/46. Here's my view:
<h1 itemprop="name"><%= #recipe.name %></h1>
<ul>
<li><%= link_to 'Edit', edit_recipe_path(#recipe) %></li>
</ul>
<p itemprop="description"><%= #recipe.description %></p>
here's my routes:
match "/:username" => "recipes#index"
scope ':username' do
resources :recipes
end
here's my show index:
def show
#user = User.find_by_username params[:username]
#recipe = Recipe.where(:user_recipe_id => params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #recipe }
end
end
and my model:
before_save :set_next_user_recipe_id
belongs_to :users
validates :user_recipe_id, :uniqueness => {:scope => :user_id}
def to_param
self.user_recipe_id.to_s
end
def set_next_user_recipe_id
self.user_recipe_id ||= get_new_user_recipe_id
end
def get_new_user_recipe_id
user = self.user
max = user.recipes.maximum('user_recipe_id') || 0
max + 1
end
attr_accessible :description, :duration, :author, :url, :name, :yield, :ingredients_attributes, :user_recipe_id, :directions_attributes, :tag_list, :image
The reason I'm doing a Recipe.where(:user_recipe_id => params[:id]) instead of Recipe.where(:id => params[:id]) is because I'm trying to get so instead of john/recipes/46 showing the 46th recipe in the database, instead to show the 46th recipe that belongs to John.
Thanks for all help!
You're only trying to look for one recipe, but your query is searching for multiples. When you use a plain where(...) without ending it with .first, Rails interprets it as "show me all (multiple) Recipes with this user id" instead of "show me the (one) recipe with this id".
So you need to either put .first at the end of your query:
#recipe = Recipe.where(:user_recipe_id => params[:id]).first
or use an ActiveRecord finder that only returns one record:
#recipe = Recipe.find_by_user_recipe_id(params[:id])

Rails 3: Using a link_to :action on an "index", isn't working

edit: The bug is that the feed_preference is always nil even after the link_to is pressed, so the (if feed_preference == nil) is always true. I still don't know what's causing this.
What this link_to is supposed to do:
When you press the link, it sorts the post index a certain way. One button sorts by trending value, another sorts by time, etc.
for some reason, in the function "make_feed_preference", the #user.feed_preference NEVER changes, even if i hard code it to #user.feed_preference = "foobar"
but it looks like redirect_to 'posts' is working fine.
<%= link_to displayIcon(1), {:action => :make_feed_preference, :id => current_user.id,
:preference => "trending value", :controller => "users"}, :method=>:post %>
in the users controller:
def make_feed_preference
#user = User.find(params[:id])
#user.feed_preference = params[:preference]
#user.save
redirect_to '/posts'
end
in the view for the posts index:
def index
#user = current_user
if #user.feed_preference == nil
#user.feed_preference = "trending value"
end
#posts = Post
unless #user.tag_list == []
#posts = Post.tagged_with(#user.tag_list, :match_all => :true)
end
if #user.feed_preference == "trending value"
#posts = #posts.order('trending_value DESC').page(params[:page]).per(5)
elsif #user.feed_preference == "time"
#posts = #posts.order('created_at DESC').page(params[:page]).per(5)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #posts }
end
end
Routes.rb
resources :users do
resources :comments
resources :posts
member do
get :following, :followers
end
collection do
post "tag_with"
post "clear_tag_list_and_preferences"
post "make_feed_preference"
end
end
Whenever I check the values, it's as if clicking the link_to does nothing.
You say it does nothing? The form doesn't even post?
If it's not posting at all... do you have your link_to in a form? If you are using the post method you have to have it in a form unless you are using something like the ujs jQuery libraries which use jQuery / Javascript to help with your 'post' operation.
Using the gem : gem 'jquery-rails'
https://github.com/indirect/jquery-rails
I would also like to see your 'rake routes'

How can I use a method action like the 'update', 'create' or 'destroy' actions (from scaffold)?

I made these changes appropriately:
Now in 'app/controllers/users_controller.rb' I have this code:
def reset
respond_to do |format|
format.html # reset.html.erb
end
end
def send_reset
respond_to do |format|
if #user.errors.empty?
...
else
format.html { render :action => 'reset' }
end
end
end
Now in 'config/routes.rb' I have this code:
resources :users do
collection do
get 'reset'
post 'reset'
get 'send_reset'
post 'send_reset'
end
end
If I submit the form ('app/views/users/reset.html.erb') related to changes
<%= form_tag( send_reset_users_path, :method => :post ) do %>
<%= text_field_tag :email %>
<%= submit_tag("Send") %>
<% end %>
the browser URL become '.../users/send_reset' but I want '.../users/reset' (I think the problem is around the 'format.html { render :action => 'reset' }' code that does not render correctly the action) or, maybe, the route.
In few words I aim to use the 'send_reset' action like I use, for example, the 'update', 'create' or 'destroy' actions (from scaffold), in my case that is without creating the 'app/views/users/send_reset.html.erb' file but just calling the action method to handle my issue. How can I make this?
The default Rails URL scheme is
:host/:controller/:action/:id
Rename your controller action from
def send_reset
end
to
def reset
end
and rename the views and routes to match this change.
However you are already using reset for get and send_reset for Post but you want them to be the same just do different things if you ask for the page or send a form POST.
def reset
case request.method
when :post
# send them an email
# redirect_to :somewhere_else
else # :get, :put, :delete
# render the view with the recovery form
end
end

Resources