Rails dataTables add link_to - ruby-on-rails

I'm using an approach from Railscast to remotely access a table for dataTables.
This is the start of the code in workorders4_datatable.rb:
class Workorders4Datatable
delegate :params, :h, :link_to, :number_to_currency, to: :#view
def initialize(view)
#view = view
end
def as_json(options = {})
{
sEcho: params[:sEcho].to_i,
iTotalRecords: Workorder.external.count,
iTotalDisplayRecords: workorders.external.total_entries,
aaData: data
}
end
private
def data
workorders.external.map do |workorder|
[
link_to(workorder.id, workorder),
h(workorder.parent.try(:id)),
h(workorder.description),
h(workorder.client.try(:client_name)),
h(workorder.woasset.try(:assetnum)),
h(workorder.type.try(:typecode)),
h(workorder.billmethod.try(:method_name)),
h(workorder.workgroup.try(:group_name)),
h(workorder.employee.try(:employee_full_name)),
h(workorder.wostatus.try(:statuscode)),
h(workorder.expenses.tobill.sum("quantity") * workorder.expenses.sum("unitcost")),
h(workorder.events.tobill.sum("hours")),
h(workorder.events.sum("hours")),
link_to('ADD Invoice', new_invoice_path(:workorder_id => workorder), :class => 'btn btn-primary')
]
end
end
All of it works except for this line:
link_to('ADD Invoice', new_invoice_path(:workorder_id => workorder), :class => 'btn btn-primary')
It causes this error:
NoMethodError - undefined method `new_invoice_path' for #<Workorders4Datatable:0x007f94513588a0>:
Yet, the following works in a different view:
<%= link_to 'ADD Invoice', new_invoice_path(:workorder_id => #workorder.id), :class => 'btn btn-primary' %>
Is there some way I can get it to work?

Have you tried to replace new_invoice_path with #view.new_invoice_path? That might work. The reason is because new_invoice_path should be called in context of the view, but it's being called in context of Workorders4Datatable.
I've seen this pattern in the past as a shortcut:
def v
#view
end
v.new_invoice_path

Related

How to reload my index page

I have this filter in my tutos index:
= simple_form_for :query, url: tutos_path, method: :get, wrapper: :inline_form, html: {class: 'form-inline'} do |f|
= f.input :keyword, placeholder: "Keyword"
= f.input :category, collection: (Category.all.map {|c| c.name}) , prompt: "Select a category"
= f.input :user, collection: (User.order('nickname ASC').all.map {|u| u.nickname}), prompt: "Select a user"
= f.button :submit, "Find", class:"btn btn-warning"
= link_to t("search_form.best"), best_voted_path, class: "btn btn-default"
= link_to t("search_form.all"), tutos_path, class: "btn btn-default"
-if user_signed_in?
= link_to t("search_form.create"), new_tuto_path, class:"btn btn-success"
After filtering I can't get back to my tutos_path through my link_to:
I have this error:
NoMethodError at /en/tutos
undefined method `[]' for nil:NilClass
in my controller I have:
def index
#tutos = Tuto.all
filter_tutos
end
def filter_tutos
#tutos = Tuto.search(params[:query][:keyword]).includes(:user, :category) if params[:query][:keyword].present?
#tutos = Tuto.joins(:user).where('users.nickname LIKE ?', params[:query][:user]) if params[:query][:user].present?
#tutos = Tuto.joins(:category).where('categories.name LIKE ?', params[:query][:category]) if params[:query][:category].present?
end
The error is coming from your params[:query][:keyword].present? and the other ones alike, because it's evaluated as params, then params[:query]. If one of these evaluates to nil, and then trying to run nil[:query], hence [] isn't defined on NilClass, it returns an error.
You'll need to check for nil in the function:
def filter_tutos
return if params[:query].nil? # Don't bother, if the query is nil
#tutos = Tuto.search(params[:query][:keyword]).includes(:user, :category) if params[:query][:keyword].present?
#tutos = Tuto.joins(:user).where('users.nickname LIKE ?', params[:query][:user]) if params[:query][:user].present?
#tutos = Tuto.joins(:category).where('categories.name LIKE ?', params[:query][:category]) if params[:query][:category].present?
end
As far as I remember, params is always set in the Controller. If this is not the case, you'll need to adapt your nil-checks for that as well.
To make it fit your own answer, and have a fallback method, you could do like so, to check if
def index
filter_tutos if params[:query].present?
#tutos ||= Tuto.all
end
To make sure that #tutos are set. It'll be set to Tuto.all if it's nil from the method filter_tutos.
I finally found out...
in my controller:
def index
if params[:query].present?
filter_tutos
else
#tutos = Tuto.all
end
end
in my view instead of my = link_to t("search_form.all"), tutos_path, class: "btn btn-default"
I did:
= link_to t("search_form.all"), {controller: 'tutos', action: 'index'}, class: "btn btn-success"

How to extract haml code into helper

if I want to move the following code into helper
%td.center= log.streaming_verification_id
%td.center= log.id
and render it by calling call_the_helper
How to write the method call_the_helper to meet my requirement
into helper
- #tool_cvt_streaming_verification_logs.each do |log|
%tr
= call_the_helper
Simply to do it by moving the code into an other view (partial), and render it from helper or another view.
view:
- #tool_cvt_streaming_verification_logs.each do |log|
%tr
= call_the_helper(log)
helper:
def call_the_helper(log)
render partial: 'partial_view', locals: { :log => log }
end
partial view:
%td.center= log.streaming_verification_id
%td.center= log.id
Put something like it in your def call_the_helper:
haml_tag :td, :class => 'center' do
log.streaming_verification_id
end
haml_tag :td, :class => 'center' do
log.id
end

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

Rails routes option "as", can't edit resource

In my application I have model "Regulation", form for creating regulations looks like this:
- if %W(edit update).include? action_name
= content_for :heading, t('partners.regulations.edit')
- else
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation] do |f|
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
- if %W(edit update).include? action_name
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
- else
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
In my routes I have:
namespace :partners do
resources :regulations, as: :rental_company_regulation, except: :show
end
My controller looks like this:
module Partners
class RegulationsController < ApplicationController
include Partners::BaseController
load_and_authorize_resource through: :rental_company, singleton: true
before_action :set_breadcrumbs
before_action :set_regulation, only: :new
def new
if #rental_company_regulation
redirect_to edit_partners_rental_company_regulation_path(#rental_company_regulation)
end
add_breadcrumb t('partners.regulations.new')
end
def create
if #regulation.save
flash[:notice] = t('partners.regulations.created')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.new')
render :new
end
end
def edit
add_breadcrumb t('partners.regulations.edit')
end
def update
if #regulation.update(regulation_params)
flash[:notice] = t('partners.regulations.updated')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.edit')
render :edit
end
end
protected
def set_regulation
#rental_company_regulation = Regulation.where(rental_company_id: rental_company).first
end
def set_breadcrumbs
add_breadcrumb current_partner.rental_company.name, :partners_root_path
end
private
def regulation_params
params.require(:regulation).permit(:content_pl, :content_en, :rental_company_id)
end
end
end
Creating resource from scratch works properly. But I went to:
"http://localhost:3000/partners/regulations/4/edit" to edit regulation I have the following error:
undefined method `partners_regulation_path' for #<#<Class:0x0000000242fae8>:0x00000007d9afb0>
I can't solve this problem. What's wrong?
Edit:
Rake routes:
partners_rental_company_regulation_index GET /partners/regulations(.:format) partners/regulations#index
POST /partners/regulations(.:format) partners/regulations#create
new_partners_rental_company_regulation GET /partners/regulations/new(.:format) partners/regulations#new
edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) partners/regulations#edit
partners_rental_company_regulation PATCH /partners/regulations/:id(.:format) partners/regulations#update
Edit2:
I've changed my form too looks like this:
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path
Now I can edit exisiting resource but can't create a new one. When I trying to create the new one I have the following error:
No route matches {:action=>"update", :controller=>"partners/regulations"} missing required keys: [:id]
What's wrong?
as
To simplify user2675613's answer, your error is basically caused by using the as argument in your routes
as: basically allows you to "name" the route:
#config/routes.rb
resources :users # -> users_path
resources :users, as: :members # -> members_path
Error
Your error is as follows:
undefined method `partners_regulation_path'
This basically means you're using a path which doesn't exist. This is because you've used the as: option in your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partners_regulation_path
end
resources :partners do
resources :regulations, as: "test" # -> partners_test_path
end
This is confirmed with your routes:
partners_rental_company_regulation_index
new_partners_rental_company_regulation
edit_partners_rental_company_regulation
partners_rental_company_regulation
Fix
The way to fix this is to remove the as: option from your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partner_regulations_path
end
Alternatively, if you wanted to keep the custom name for your paths, you'll have to change your path references to parental_company_regulation_path
As you can see you in your rake routes your url to edit a regulation is edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) and to create a new one the url is new_partners_rental_company_regulation GET /partners/regulations/new(.:format).
You need to change the way you are using your form here. You can create a partial for all the common fields of form but you need to separate the url part in your form to make a create and update requests.
You can make a partial _form.html.haml with contents:
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
Then inside your edit.html.haml you can have:
= content_for :heading, t('partners.regulations.edit')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
Similarly inside your new.html.haml you can have:
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_index_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"

Parameter in AJAX request

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");

Resources