Parameter in AJAX request - ruby-on-rails

I have a view which contain multiple links:
<% a.each do |q| %>
<%= link_to "stock it",
{ :action => "stock",
:qid => q.question_id,
:qur => q.question_answers_url,
:qti => q.title } ,
:remote => true %>
<div id="<%= "stock" + q.question_id.to_s %>"></div>
<% end %>
Each link generate AJAX-request. Here is a controller:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
respond_to do |format|
format.js { render :layout=>false }
end
end
Now return to the view. Each link has a 'div' with unique id='stock'. When user press the link I need to add text to specific div with corresponding id.
I have a stock.js.erb file:
$("#stock<number>").html("some text");
How can I pass div-id to stock.js.erb and how can I use it ?

Common use is to add object.id to your DOM id. That what you exactly did:
<div id="<%= "stock_#{q.question_id}" %>"></div>
Then in your controller you shoud define your question_id or your exact question:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
#question_id = params[:qid]
end
Now it will be shared with your stock.js.erb file:
$("#stock_<%= #question_id %>").html("some text");

Related

How to add a field into a snippet in Comfortable Mexican Sofa

I plan to use snippets in Comfortable Mexican Sofa to store email templates. But is there a way to add a field into a snippet. I would use it to store the subject of the email. Would be good to have also the subject in the cms so that our editors can change it if they feel like it.
By default snippets seem to have only two fields 'Label' and 'Identifier'. And of course the 'Content'. I would like to add also a 'Subject' String into the fields.
Simple Three Step Process:
1:
rails g migration AddSubjectToComfyCmsSnippets subject:string
2:
rake db:migrate
3:
create app/views/comfy/admin/cms/snippets/_form.html.haml with the following content:
- content_for :right_column do
= render 'comfy/admin/cms/files/index'
= render :partial => 'comfy/admin/cms/partials/snippet_form_before', :object => form
= form.text_field :label, :data => {:slugify => #snippet.new_record?}
= form.text_field :identifier, :data => {:slug => true}
= form.text_field :subject
= form.text_area :content, :data => {'cms-rich-text' => true}
= render :partial => 'comfy/admin/cms/categories/form', :object => form
= render :partial => 'comfy/admin/cms/partials/snippet_form_after', :object => form
= form.form_group :class => 'form-actions' do
= form.submit t(#snippet.new_record?? '.create' : '.update'), :class => 'btn btn-primary'
= link_to t('.cancel'), comfy_admin_cms_site_snippets_path, :class => 'btn btn-link'
Now you can reference the subject in your app like so:
Subject: #{#snippet.subject}
Monkey patch to get fixtures working:
create config/initializers/cms_monkey_patch.rb with the following contents:
ComfortableMexicanSofa::Fixture::Snippet::Importer.class_eval do
def import!
Dir["#{self.path}*/"].each do |path|
identifier = path.split('/').last
snippet = self.site.snippets.find_or_initialize_by(:identifier => identifier)
# setting attributes
categories = []
if File.exists?(attrs_path = File.join(path, 'attributes.yml'))
if fresh_fixture?(snippet, attrs_path)
attrs = get_attributes(attrs_path)
snippet.label = attrs['label']
snippet.subject = attrs['subject']
categories = attrs['categories']
end
end
# setting content
%w(html haml).each do |extension|
if File.exists?(content_path = File.join(path, "content.#{extension}"))
if fresh_fixture?(snippet, content_path)
snippet.content = extension == "html" ?
::File.open(content_path).read :
Haml::Engine.new(::File.open(content_path).read).render.rstrip
end
end
end
# saving
if snippet.changed? || self.force_import
if snippet.save
save_categorizations!(snippet, categories)
ComfortableMexicanSofa.logger.info("[FIXTURES] Imported Snippet \t #{snippet.identifier}")
else
ComfortableMexicanSofa.logger.warn("[FIXTURES] Failed to import Snippet \n#{snippet.errors.inspect}")
end
end
self.fixture_ids << snippet.id
end
# cleaning up
self.site.snippets.where('id NOT IN (?)', fixture_ids).each{ |s| s.destroy }
end
end
end
ComfortableMexicanSofa::Fixture::Snippet::Exporter.class_eval do
def export!
prepare_folder!(self.path)
self.site.snippets.each do |snippet|
snippet_path = File.join(self.path, snippet.identifier)
FileUtils.mkdir_p(snippet_path)
# writing attributes
open(File.join(snippet_path, 'attributes.yml'), 'w') do |f|
f.write({
'label' => snippet.label,
'subject' => snippet.subject,
'categories' => snippet.categories.map{|c| c.label}
}.to_yaml)
end
# writing content
open(File.join(snippet_path, 'content.html'), 'w') do |f|
f.write(snippet.content)
end
ComfortableMexicanSofa.logger.info("[FIXTURES] Exported Snippet \t #{snippet.identifier}")
end
end
end

Filter field based on previous field selection

How can I use simple_form to filter a field, based on a previous fields value?
For instance, I have an Opportunities form, with two fields, Company and Contact.
Company Field:
<div class="form-group">
<%= f.association :company, collection: Company.all.order(:account), prompt: "", :label_method => :account, :value_method => :id %>
</div>
Contact Field:
<div class="form-group">
<%= f.association :contact, collection: Contact.all.order(:first_name), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
</div>
Here is what I want to do: If I select a company called "Deviant" from the Company field above, I want the Contact field to only display those contacts associated with the company called "Deviant".
I am trying something like this, but can't get it to work:
<div class="form-group">
<%= f.association :contact, collection: Contact.where("company_id = ?", params[:id]), prompt: "", :label_method => lambda { |contact| "#{contact.first_name} #{contact.last_name}" }, :value_method => :id %>
</div>
I don't know how to reference the value in the Company field.
How can I do this?
Thanks.
Update
Anyone? Surely this must be possible. This is a key functionality in any form. I would hope I don't need jQuery or something.
I think the best approach is to use ajax requests to update your contacts collection dinamically whenever the company's selected value is changed.
First you'll need an action in your contacts controller:
app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def contacts_list
if params[:company_id]
#contacts = Contact.where(company_id: params[:company_id])
else
#contacts = Contact.all
end
respond_with(#contacts) do |format|
format.json { render :json => #contacts.to_json(:only => [:id, :first_name, :last_name]) }
end
end
end
Add this to your routes:
config/routes.rb
post 'contacts_list' => "contacts#contacts_list", as: :contacts_list
Then use the coffeescript code bellow to populate your contacts' collection:
app/assets/javasctipts/companies.js.coffee
$(document).ready ->
if $("#opportunity_company_id")
populate_contacts()
$("#opportunity_company_id").change ->
populate_contacts()
populate_contacts = ->
$contacts_select = $("select#opportunity_contact_id")
$contacts_select.attr "disabled", "disabled"
company_id = $("select#opportunity_company_id").val()
if company_id is ""
$contacts_select.html "<option value=\"\">(select the company first)</option>"
else
$contacts_select.html "<option value=\"\">(loading contacts...)</option>"
data = {company_id: company_id}
data[window._auth_token_name] = window._auth_token
$.ajax "/contacts_list",
type: "post"
dataType: "json"
data: data
success: (contacts) ->
_html = '<option value="">Select the contact:</option>'
_html += '<option value="'+contact.id+'">'+contact.first_name + ' ' + contact.last_name + '</option>' for contact in contacts
$contacts_select.html _html
$contacts_select.removeAttr "disabled"
error: ->
alert 'Error trying to load contacts.'
Finally, inside your html's head tag:
<% if protect_against_forgery? %>
<script>
window._auth_token_name = "<%= request_forgery_protection_token %>";
window._auth_token = "<%= form_authenticity_token %>";
</script>
<% end %>
Hope it helps...
update:
Add the following line to your ApplicationController (app/controllers/application_controller.rb):
respond_to :html, :xml, :json, :js

Ruby on Rails remote form not updating the page

UPDATE
I have mange to get it working by changing the Model call from
#comments = VideoComment.all(:conditions => { :video_id => #video.id}, :limit => 5, :order => :created_at)
#comments = VideoComment.last(5).reverse
It works, but it gives me the last video comments from all the videos whereas I only want those from the current video (#video.id).
Any clue on how to do that?
I have a Videocontroller and a VideoComments controller which manages the comments for the Video controller. I am trying to make my remote form update the comments list with ajax but it does not seem to work. Can you find what I did wrong?
HTML code of the show page :
- if current_user
#comment-form
= render 'video_comments/comment_form'
%ul
#comments
= render #comments
video_comments/_comment_form.html.haml
= form_for current_user.video_comments.build(:video_id => params[:id]), :remote => true do |f|
.form-fields
.comment-content
= f.text_area :content, rows:2
= f.hidden_field :video_id
= f.hidden_field :user_id
.submit-form
= f.submit "Add a comment", :class => "btn btn-default "
The Video_Commentscontroller createaction :
def create
#comment = VideoComment.create(params[:video_comment])
#video = #comment.video
#comments = VideoComment.all(:conditions => { :video_id => #video.id}, :limit => 5, :order => :created_at)
render :toggle
end
The toggle.js.erb file which manages the page changes :
$("#comment-form").html("<%= escape_javascript render 'comment_form' %>");
$("#comments").html("<%= escape_javascript render #comments %>");
If you are using Rails 3 you can do
#comments = VideoComment.where(:video_id => #video.id).order(:created_at).limit(5)
Or if you have relations properly defined you can also do
#comments = #video.comments.order(:created_at).limit(5)

Dynamically pass Hash value to a partial

I faced a problem to pass the hash value to partial file dynamically. I displayed the person names on my page (this is a partial). The hash value is like this:
names[1] = "James"
names[2] = "Williams"
names[3] = "Jack"
render :partial => "list", :locals => {:names => names}
I need to pass the hash value dynamically. How can I do that? In the example, the new hash is like this:
names[21] = 'Flink'
names[81] = 'Mark'
My code
class PrlcController < ApplicationController
def bar
#names = Hash.new
#names[1] = "James"
#names[2] = "Williams"
#names[3] = "Jack"
end
def foo_ajax
#names = Hash.new
#names[21] = 'Flink'
#names[81] = 'Mark'
end
end
bar.rhtml
----------
<!-- Name listing section -->
<%= render :partial => "list", :locals => "{:names => #names}" %>
<!-- AJAX calling section -->
<%= link_to_function "call testing", :onclick => "load_foo_ajax_data" %>
<!-- AJAX section -->
<div id="foo_ajax_data">
</div>
<!-- script section -->
function load_foo_ajax_data() {
new Ajax.Updater("foo_ajax_data","/Prlc/foo_ajax", {
asynchronous:true,
evalScripts:true,
onComplete:function(request){
},
onLoading:function(request){}
});
}
foo_ajax.rhtml
--------------
Some process here.
_list.rhtml
-----------
Display the names
Try following
class PrlcController < ApplicationController
def bar
#names = Hash.new
#names[1] = "James"
#names[2] = "Williams"
#names[3] = "Jack"
end
def foo_ajax
#names = Hash.new
#names[1] = 'Flink'
#names[2] = 'Mark'
render :update do |page|
page.replace_html 'foo_ajax_data', :partial => "list", :object => [#names]
end
end
end
bar.rhtml
<%= render :partial => "list", :locals => "{:names => #names}" %>
<!-- AJAX section -->
<div id="foo_ajax_data">
<!-- Name listing section -->
</div>
<!-- AJAX calling section -->
<%= link_to_remote "call testing", :url => { :action => "load_foo_ajax_data"} %>

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Resources