ajax-datatables-rails How to add buttons in ajax response - ajax

My problem is that I don't know how to add different buttons that remain in a condition using the gem for server side processing ajax-datatables-rails. For example before trying to do sever side processing I had this in my view.
<% if current_user.sales_manager? || current_user.admin? %>
<td>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
bill_sale_path(bill_sale),
:method => :delete %>
</td>
<% end %>
and following the tutorial in the main page of the gem, in bill_sale_datatable.rb I have this.
def data
records.map do |record|
[
link_to('Show', bill_sale_path(record), class: 'btn-xs btn-link'),
record.customer.name,
record.seller.name,
l(record.date_sold, format: :short),
record.payment_type.name,
record.payed,
number_to_currency(record.total),
CONDITION AND BUTTON HERE
]
end
end
Then, how do I use the server side processing to provide different buttons that belongs to an if condition?

While I haven't used the gem, I have used datatables with Rails and this is what I did:
Store the button as a variable before the array and then just call the variable in the array.
records.map do |record|
record_button = ''
record_button = button_to('A', button1_path) if condition1
record_button = button_to('B', button2_path) if condition2
record_button = button_to('C', button3_path) if condition3
record_button = button_to('D', button4_path) if condition4
[
link_to('Show', bill_sale_path(record), class: 'btn-xs btn-link'),
record.customer.name,
record.seller.name,
l(record.date_sold, format: :short),
record.payment_type.name,
record.payed,
number_to_currency(record.total),
record_button
]
end
You could also use a case statement if that suited your needs.
Make sure you add
def_delegator :#view, :button_to
To the top of your file as per:
https://github.com/jbox-web/ajax-datatables-rails#using-view-helpers

Related

Paginating no Active Records with will_paginate just show the values for the first page, the next pages are completely empty

I'm trying to paginate some results using the will_paginate gem in Ruby on Rails. The thing is the results are non Active Records so I follow the steps here: https://www.rubydoc.info/github/mislav/will_paginate/WillPaginate/Collection
to be able to do that, but the problem is that now I'm just able to see the results for the first page, the next pages are completely empty. I verified that the query has results for the next pages and everything looks good.
This is the code I wrote, any idea guys. Thanks!
I attached some pictures to show you guys how looks like, one is from the first page results and the other is from the second page results.
# controller AssetController
require Rails.root.to_s + '/config/initializers/will_paginate_array'
class AssetController < ApplicationController
before_action :require_login
def index
#search = params[:search]
#assetType = params[:assetType]
#searchBy = params[:searchBy]
limit = 30
currentPage = params[:page];
if currentPage == nil
currentPage = 1
end
offset = (currentPage.to_i - 1) * limit
count = Assets.getAssetsCount()
results = Assets.getAllAssets(offset, limit)
if results.class == Array
#assets = results.paginate_custom_array(currentPage, limit, count)
else
# TODO
end
end
# config/initializers/will_paginate_array.rb
require 'will_paginate/collection'
Array.class_eval do
def paginate_custom_array(page = 1, per_page = 15, size)
WillPaginate::Collection.create(page, per_page, size) do |pager|
pager.replace self[pager.offset, pager.per_page].to_a
end
end
end
# views/asset/index.erb
<div id="assets_results">
<%= render 'partials/assets_result' %>
</div>
# views/asset/index.js.erb
$("#assets_results").html("<%= escape_javascript render("partials/assets_result") %>");
$('#paginator').html('<%= escape_javascript(will_paginate(#assets, :remote => true).to_s) %>');
# views/partial/_assets_result.html.erb
<% #assets.each do |asset| %>
<tr>
<td>
...
</td>
</tr>
<% end %>
<div class="text-center">
<div id="paginator"class="pagination pagination-lg">
<%= will_paginate #assets, :remote => true %>
</div>
</div>
You are applying pagination logic twice.
First, you select only one page of results from your Assets.getAllAssets method:
count = Assets.getAssetsCount()
results = Assets.getAllAssets(offset, limit)
Then, you pass that single page of 30 records into will_paginate's own pagination methods, which cannot show you results 31..60 if you only give it a single page of 30 results.
You should either drop your will_paginate logic, or change your getAllAssets method to return something like an ActiveRecord::Relation that can have a limit/offset applied to it by will_paginate.

Ruby - trying to make hashtags within string into links

I am trying to make the hashtags within a string into links.
e.g. I'd like a string that's currently: "I'm a string which contains a #hashtag" to transform into: "I'm a string which contains #hashtag"
The code that I have at the moment is as follows:
<% #messages.each do |message| %>
<% string = message.content %>
<% hashtaglinks = string.scan(/#(\d*)/).flatten %>
<% hashtaglinks.each do |tag| %>
<li><%= string = string.gsub(/##{tag}\b/, link_to("google", "##{tag}") %><li>
<% end %>
<% end %>
I've been trying (in vain) for several hours to get this to work, reading through many similar stackoverflow threads- but frustration has got the better of me, and as a beginner rubyist, I'd be really appreciate it if someone could please help me out!
The code in my 'server.rb' is as follows:
get '/' do
#messages = Message.all
erb :index
end
post '/messages' do
content = params["content"]
hashtags = params["content"].scan(/#\w+/).flatten.map{|hashtag|
Hashtag.first_or_create(:text => hashtag)}
Message.create(:content => content, :hashtags => hashtags)
redirect to('/')
end
get '/hashtags/:text' do
hashtag = Hashtag.first(:text => params[:text])
#messages = hashtag ? hashtag.messages : []
erb :index
end
helpers do
def link_to(url,text=url,opts={})
attributes = ""
opts.each { |key,value| attributes << key.to_s << "=\"" << value << "\" "}
"<a href=\"#{url}\" #{attributes}>#{text}</a>"
end
end
Here is the code to get you started. This should replace (in-place) the hashtags in the string with the links:
<% string.gsub!(/#\w+/) do |tag| %>
<% link_to("##{tag}", url_you_want_to_replace_hashtag_with) %>
<% end %>
You may need to use html_safe on the string to display it afterwards.
The regex doesn't account for more complex cases, like what do you do in case of ##tag0 or #tag1#tag2. Should tag0 and tag2 be considered hashtags? Also, you may want to change \w to something like [a-zA-Z0-9] if you want to limit the tags to alphanumerics and digits only.

Rails 3: Loop shows more records than there should be

Not exactly sure of what to call this issue. Still new to rails.
Situation: An auction contains many lots.
I'm showing an auction's lots in a url like /auctions/3/lots/.
View:
<ul>
<% #lots.each do |lot| %>
<li><%= lot.auction_id %>: <%= lot.id %></li>
<% end %>
</ul>
Outputs this:
<ul>
<li>3: 1</li>
<li>3: </li>
</ul>
I only have one lot in my database. Not sure where the extra loop instance is coming from.
This happens on any lot listing no matter which auction I'm looking at.
Also,
<%= #lots.length %> displays 2
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
My lots_controller looks like this:
def index
#auction = Auction.find(params[:auction_id])
#lots = #auction.lots
end
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.build(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end
My models:
class Auction < ActiveRecord::Base
...
has_many :lots
end
class Lot < ActiveRecord::Base
belongs_to :auction
...
end
The ...s are just attr_accesssible and validates lines.
The log when I hit the page was requested, here it is.
Started GET "/auctions/8/lots" for 127.0.0.1 at 2013-02-13 16:35:51 -0500
Processing by LotsController#index as HTML
Parameters: {"auction_id"=>"8"}
Auction Load (0.1ms) SELECT "auctions".* FROM "auctions" WHERE "auctions"."id" = ? LIMIT 1 [["id", "8"]]
Lot Load (0.2ms) SELECT "lots".* FROM "lots" WHERE "lots"."auction_id" = 8
[#<Lot id: 18, description: "1923 Morgan", lot_number: 1, auction_id: 8, created_at: "2013-02-13 17:20:04", updated_at: "2013-02-13 17:20:04">]
Rendered layouts/_messages.html.erb (0.1ms)
Lot Exists (0.2ms) SELECT 1 AS one FROM "lots" WHERE "lots"."auction_id" = 8 LIMIT 1
Rendered lots/index.html.erb within layouts/application (9.4ms)
Completed 200 OK in 21ms (Views: 17.8ms | ActiveRecord: 0.5ms)
Update:
Someone mentioned that it looks like I'm using #auction.lots.build somewhere.
And yes, I am. I have a form on the same page (index) where I can add lots.
<%= form_for(#auction.lots.build, :url => auction_lots_path(#auction)) do |f| %>
...
<% end %>
Changing #auction.lots.build got rid of the extra row, although now I can't create lots successfully. I'm not sure what to do. I probably have to set up something in the index method of the lots_controller, but I don't know what.
Any help is appreciated.
This would happen in your create method if the lot failed to save. Because you used #auction.lots.build, that appends a lot record to the auction. If it doesn't save properly, it's still there unsaved. That explains why the "mystery" one doesn't have an id, and also why:
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
#lots.count is a database query, but #lots.size is just the size of the array in memory.
I would probably do something more like this in the create action:
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.create!(params[:lot])
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
rescue ActiveRecord::RecordInvalid
render :action => "index"
end
... but of course others will prefer using if/else rather than rescuing the exception. There are other ways around this. You could do #auction.reload.lots to cull the unsaved one, but that's a little wierd. The normal rails thing to do in this case is re-render the form with the validation errors displayed and ask the user to fix them and try creating again.
This should help:
def create
params[:lot].merge!({:auction_id => params[:auction_id]})
#lot = Lot.new(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end

How to generate pages for each tag in nanoc

I am new to nanoc and I am still finding my around it. I am able to get my site ready, it looks good and functions good, too. But I need to have a tags area. I am able to achieve that with
<%= tags_for(post, params = {:base_url => "http://example.com/tag/"}) %>
But how do I generate pages for tag? So for instance there is a tag called "NFL", so every time a user clicks on it, he/she should be directed to http://example.com/tag/nfl with a list of articles that correspond with NFL.
I can setup a layout which will do that. But then what kind of logic should be I using? And also do I need to have a helper for this?
You can use a preprocess block in your Rules file in order to generate new items dynamically. Here’s an example of a preprocess block where a single new item is added:
preprocess do
items << Nanoc::Item.new(
"some content here",
{ :attributes => 'here', :awesomeness => 5000 },
"/identifier/of/this/item")
end
If you want pages for each tag, you need to collect all tags first. I’m doing this with a set because I do not want duplicates:
require 'set'
tags = Set.new
items.each do |item|
item[:tags].each { |t| tags.add(t.downcase) }
end
Lastly, loop over all tags and generate items for them:
tags.each do |tag|
items << Nanoc::Item.new(
"",
{ :tag => tag },
"/tags/#{tag}/")
end
Now, you can create a specific compilation rule for /tags/*/, so that it is rendered using a "tags" layout, which will take the value of the :tag attribute, find all items with this tag and show them in a list. That layout will look somewhat like this:
<h1><%= #item[:tag] %></h1>
<ul>
<% items_with_tag(#item[:tag]).each do |i| %>
<li><%= link_to i[:title], i %></li>
<% end %>
</ul>
And that, in broad strokes, should be what you want!

Rails 3 refactoring issue

The following view code generates a series of links with totals (as expected):
<% #jobs.group_by(&:employer_name).sort.each do |employer, jobs| %>
<%= link_to employer, jobs_path() %> <%= "(#{jobs.length})" %>
<% end %>
However, when I refactor the view's code and move the logic to a helper, the code doesn't work as expect.
view:
<%= employer_filter(#jobs_clone) %>
helper:
def employer_filter(jobs)
jobs.group_by(&:employer_name).sort.each do |employer,jobs|
link_to employer, jobs_path()
end
end
The following output is generated:
<Job:0x10342e628>#<Job:0x10342e588>#<Job:0x10342e2e0>Employer A#<Job:0x10342e1c8>Employer B#<Job:0x10342e0d8>Employer C#<Job:0x10342ded0>Employer D#
What am I not understanding? At first blush, the code seems to be equivalent.
In the first example, it is directly outputting to erb, in the second example it is returning the result of that method.
Try this:
def employer_filter(jobs)
employer_filter = ""
jobs.group_by(&:employer_name).sort.each do |employer,jobs|
employer_filter += link_to(employer, jobs_path())
end
employer_filter
end
Then call it like this in the view:
raw(employer_filter(jobs))
Also note the use of "raw". Once you move generation of a string out of the template you need to tell rails that you don't want it html escaped.
For extra credit, you could use the "inject" command instead of explicitly building the string, but I am lazy and wanted to give you what I know would work w/o testing.
This syntax worked as I hoped it would:
def employer_filter(jobs_clone)
jobs_clone.group_by(&:employer_name).sort.collect { |group,items|
link_to( group, jobs_path() ) + " (#{items.length})"
}.join(' | ').html_safe
end

Resources