Get Post Full Path in Jekyll/Octopress - ruby

In Octopress, I'm trying to get a post's full file path (something like ~/projects/site/source/_posts/2012-01-01-something.markdown) by extending the Jekyll:Post class.
module Jekyll
class Post
alias_method :original_to_liquid, :to_liquid
def to_liquid
# test if this function is actually called
puts "hello"
original_to_liquid.deep_merge({
'full_path' => File.join(#base,#name)
})
end
end
end
I name this file as full_path.rb and put it in the plugins folder. Oddly, my to_liquid function never get called, since the hello message didn't show up.
Even more strange, I find the date.rb shipped with Octopress also defines to_liquid method of class Post, so I add the full_path => File.join(#base,#name) line there and it works! I'm soooo confused.
So my question is, why my to_liquid method didn't get called?
UPDATE
After upgrading jekyll from 0.12.0 to 1.2.1, it magically works......

You might take a look at the Post#permalink documentation. It should do what you want without having to create new plugins.
(if I misunderstood you, maybe containing_dir is the method you're looking for)

Related

What are the ways to override a frozen variable in ruby?

This is a selenium-webdriver commands.rb file where I want to edit the upload_file key of COMMANDS variable from [:post, 'session/:session_id/se/file'] to [:post, 'session/:session_id/file']. I want to extend this class to one of mine's and make this change permanent so that even if i bundle install it, this change shouldn't be gone.
module Selenium
module WebDriver
module Remote
module W3C
class Bridge
COMMANDS = {
upload_file: [:post, 'session/:session_id/se/file']
}.freeze
end
end
end
end
end
You can get around the issue of unfreezing by just assigning the constant to a new value:
Selenium::WebDriver::Remote::W3C::Bridge.const_set(:COMMANDS, {
upload_file: [:post, 'session/:session_id/file']
}.freeze)
You will get a warning, but it will work.
If you really want to unfreeze, I have to point you to another question on the topic: How to unfreeze an object in Ruby?
in response to comment
The easiest way is to use ActiveSupport Hash#deep_dup from ActiveSupport. If this is a non-rails project, you can add the activesupport gem and require 'active_support/all':
my_commands = Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS.deep_dup
# Here we can change one key only, or do any other manipulation:
my_commands[:upload_file] = [:post, 'session/:session_id/file']
Selenium::WebDriver::Remote::W3C::Bridge.const_set(:COMMANDS, my_commands)
You can also do it without ActiveSupport, but you will need to be a little more careful about how you clone the object because deep_dup is not available, something like this would work instead:
my_commands = Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS.clone.transform_values(&:clone)
And then run the same stuff as in the previous example.
To understand this, read up on the difference between a "shallow" vs "deep" copy of an Object in Ruby, or the difference between "clone" and "deep_dup". Also see Hash#transform_values which I used in that snippet, if you're not familiar with it.

How to call a method on a local variable in Ruby?

Probably a stupid question but I was following along this article and came across a bit of code I couldn't quite grasp. Here it is:
class CreateArticle
attr_reader :validate_article, :persist_article
def initialize(validate_article, persist_article)
#validate_article = validate_article
#persist_article = persist_article
end
def call(params)
result = validate_article.call(params)
if result.success?
persist_article.call(params)
end
end
end
More specifically, the problematic line is this:
if result.success?
Here's my problem with it: where did the success? method come from? It's not default in Ruby, and result is a local variable, so it should be nearby. But even if it's just omitted in the code sample, where would it have to be defined for that line to work? Everywhere I tried to define it just gave me an 'undefined method' error.
For example, I tried to define it both in the CreateArticle class and in the (only alluded to) ValidateArticle class, the obvious culprits, but no dice.
Update:
The reason I ask is not so much about what success? does as it is because I'm interested in using the pattern in my code. So, for example, my version of the success? method could be just checking whether a value got updated, or an item was inserted into an array. For example, let's say it's just this:
def success? # or self.success?
return true
end
Problem is, I can find no place where I can put this that works. I even created a module just for it and included it into the class, and still it doesn't work (it just returns 'undefined method'). So I'm still at a loss as to where I would have to define such a method so that it would work the way it looks like it should.
It's a method that comes with rails. It checks.for a server response with a 200 code. If it gets a 200 code it returns true else it returns false. Read the rails API docs about it... https://apidock.com/rails/v3.2.3/ActiveResource/Response/success%3F
Actually . success? is a built in ruby method. Check here. What it actually does is checking Stat and returns a boolean.
I did some more digging around the blog and from what I found I suspect that the code is probably making use of the dry-monads gem:
You can explicitly check the type by calling failure? or success? on a monadic value.
It's not explicit in the code excerpt but it's the only thing that makes sense.

Unknown response for all methods and commands in ruby-asterisk

Testing ruby-asterisk manager interface with ruby version 1.9.3p0 and gem 1.8.11, for all command and methods its printing the the same output.
Anyone faced similar problem.
Code:
#!/usr/bin/env ruby
require 'ruby-asterisk'
#ami = RubyAsterisk::AMI.new("192.168.1.5",5038)
#ami.login("admin","passs")
puts #ami.command("sip show peers")
Output:
#<RubyAsterisk::Response:0x000000016af710>
Project URL
Problem solved. Didn’t check the readme RESPONSE OBJECT section.
It's working.
var = #ami.command(""sip show peers)
puts var.data
You are putting the Instance of the RubyAsterix. I think after haveing a brief look at the project that most/all of the instance methods returns the instance it self. The reason for doing it that way is that it makes it very easy to chain multiplie actions which makes for a nice syntax/usage.
I think you should remove the puts and allow the gem to display what it wants to display.

How can I run a method at the end of a file from a gem?

I have a gem (e.g. mygem) and as is normal, I add mygem to a file by putting require "mygem" at the top. What if I have a method in mygem called finish_jobs and I want it to run in the following location:
require "mygem"
# code, code code
finish_jobs
How would I do that without forcing the user to add the method every time they use the gem?
Specifically, what I am trying to do is write a server app (with rack) and I need the methods in the body of the file to be processed before the server is started.
This is certainly possible.
Why not just add the code directly into the Gem (since it sounds like it is under your control and is not an external dependency)?
module MyGem
def printSomething
p 2 + 2
end
module_function :printSomething
printSomething()
# => 4
end
If this isn't what you had in mind, let me know and I can update the solution.
Also, see Kernel#at_exit
A more explanatory guide on Kernel#at_exit
I don't know of a way to do what you're describing.
One workaround would be to provide an API which accepts a block. This approach allows you to run code after the user's setup without exposing implementation details to them.
A user could call your library method, providing a block to set up their server:
require "mygem"
MyGem.code_code_code {
# user's code goes here
}
Then, your library code would:
Accept the block
Call some library code
Here's an example implementation:
module MyGem
# Run some user-provided code by `yield`-ing the block
# Then run the gem's finalizer
def self.code_code_code
# Execute the block:
yield
# Finalize:
finish_jobs
end
end
This way, you can accept code from the user but still control setup and finalization.
I hope it helps!

How to force Kaminari to always include page param?

Kaminari's URL generation omits the page param if it is generating the link back to the first page. However, the application is designed to select a random page if the page parameter is omitted. Kaminari's default behaviour, then, precludes paginating back to the first page in a reliable way.
I've resolved this issue, and will post my solution below a bit later, but I wanted to post this question for posterity, and I'm also pretty new to Rails, thus I'm not sure my solution is the best or most elegant, and I'm interested in improvements and refinements, if just for my own selfish edification!
The line of code in Kaminari that implements the behaviour we want to change is in lib/kaminari/helpers/tags.rb, in the method Kaminari::Helpers::Tag::page_url_for.
def page_url_for(page)
#template.url_for #template.params.merge(#param_name => (page <= 1 ? nil : page))
end
To override this behaviour, I created a file lib/kaminari/helpers/tag.rb, containing the following:
module Kaminari
module Helpers
class Tag
def page_url_for(page)
#template.url_for #template.params.merge(#param_name => (page < 1 ? nil : page))
end
end
end
end
I then patched in the file by adding the following line to config/initializers/extensions.rb:
require "lib/kaminari/helpers/tag.rb"
My apologies for any awkwardness with the Ruby/Rails terminology, I'm still fairly new to Ruby. Comments and criticisms are welcome.
UPDATE
The new version of the kaminari source will require this as the updated line:
#template.url_for #params.merge(#param_name => (page))
Otherwise you will lose other params passed into your pagination call.
For clairity sake here is the full output of the new code:
module Kaminari
module Helpers
class Tag
def page_url_for(page)
#template.url_for #params.merge(#param_name => (page))
end
end
end
end
You will still place this inside an initializers file as Daniel suggested.
As of today (July 2016), the Kaminari master branch includes a config option params_on_first_page, which is false by default.
Setting this config option to true will include page params for all pages, including page 1.
Note that the master branch isn't a stable release, so use with caution!
This is the answer for 2018 as am writing this :
Like it's stated in the kaminari github home page
Run this to create a config file for kaminari :
rails g kaminari:config
This will create a file kaminari_config.rb in your config/initializers folder
Uncomment the line : config.params_on_first_page = false and replace false by true :
config.params_on_first_page = true
Restart your server if necessary. That's it :)

Resources