How to get a string from Proc.new

Added by Tide _ about 9 years ago

I am trying to create a plugin. In my init.rb I am reading a setting.
I am doing it like this : @new_window = Proc.new { Setting.plugin_test['new_window'] }
When I try to say if @new_window == "0" I am not getting a string.
I actually end up with an object that is still a proc.

How do I convert this to a string so I can see if it is 0 or 1?
I can see the setting in my database so I know I am just down to converting this proc to a string.

Thanks

Replies (28)

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Maybe

if @new_window[] == "0" 

or
if @new_window.call == "0" 

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Thanks for the suggestion Yuki. I tried both of those and still get and error " undefined method `plugin_test' ". The only example I can find is in lib/redmine/menu_manager.rb. You can pass a proc for :caption and it will turn it into a string like this.

I pass

:caption => Proc.new { Setting.plugin_test['item_name'] }

and it turns this into a string like this :
if @caption.is_a?(Proc)
c = @caption.call(project).to_s

I just can't make mine work like this.

Any more suggestions?

p.s. - This is what you get instead of the actual value of new-window :

#<Proc:0x00006bfe4e40e8c8@/home/user/rails/redmine/vendor/plugins/test/init.rb:19>

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

If you want to use your plugin settings, you should call "settings" in init.rb like this.

  settings :default=>{'item_name'=>'0'}, :partial => 'settings/test_settings'

And make the view file (test/view/settings/_test_settings.html.erb)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

I already have the settings set up that way. I am just trying to actually read them from inside the init.rb. This seems to change things or something. I am doing an if statement and I can't get it to work as I can't figure out a way to get the setting. I am just not that good at Ruby.

I am wanting to have an option to open the link in a new window like. Here is the bulk of the init.rb. You would think this would work but it does not. For my Proc I get what I above. However the Proc passed as :caption gets handled correctly via the code I posted above. I just need to figure out how to get he actual string so I can do my if statement.

settings :default => {
    'link_item_name' => 'Example Link',
    'new_window' => '0'

  }, :partial => 'settings/menulink_settings'

  @new_window = Proc.new { Setting.plugin_menu_link['new_window'] }

  if @new_window == "0" 
      menu(:top_menu, 
     :link,
     "http://www.google.com",
     :caption => Proc.new { Setting.plugin_menu_link['link_item_name'] })
  else
    menu(:top_menu, 
     :link,
     "http://www.google.com",
         :caption => Proc.new { Setting.plugin_menu_link['link_item_name'] },
     :html => { :target => '_blank' })
  end

Thanks for your help Yuki!

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

I understand your problem.
You cannot read the plugin settings before the plugin registration done.
So first of all, you should register the plugin,
and then override the plugin property "menu" like this.

Redmine::Plugin.register :menu_link do
  name 'Menu link'
  author 'Your name'
  settings :default => {
    'link_item_name' => 'Example Link',
    'new_window' => '0'
  }, :partial => 'settings/menulink_settings'
end

@new_window = Proc.new { Setting.plugin_menu_link['new_window'] }

if @new_window.call == "0" 
  Redmine::Plugin.find('menu_link').menu(:top_menu, 
  :link,
  "http://www.google.com",
  :caption => Proc.new { Setting.plugin_menu_link['new_window'] })
else
  Redmine::Plugin.find('menu_link').menu(:top_menu, 
  :link,
  "http://www.google.com",
  :caption => Proc.new { Setting.plugin_menu_link['new_window'] },
  :html => { :target => '_blank' })
end

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

fixed

Redmine::Plugin.register :menu_link do
  name 'Menu link'
  author 'Your name'
  settings :default => {
    'link_item_name' => 'Example Link',
    'new_window' => '0'
  }, :partial => 'settings/menulink_settings'
end

if Setting.plugin_menu_link['new_window'] == "0" 
  Redmine::Plugin.find('menu_link').menu(:top_menu, 
  :link,
  "http://www.google.com",
  :caption => Proc.new { Setting.plugin_menu_link['link_item_name'] })
else
  Redmine::Plugin.find('menu_link').menu(:top_menu, 
  :link,
  "http://www.google.com",
  :caption => Proc.new { Setting.plugin_menu_link['link_item_name'] },
  :html => { :target => '_blank' })
end

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Still getting this error

undefined method `plugin_menu_link' for #<Class:0x744a24489df0>

It is coming from this line

if Setting.plugin_menu_link['new_window'] == "0" 

I have found I need to use this on that line

Setting.plugin_menu_link['new_window']

But then I get this error

Redmine::PluginNotFound (Redmine::PluginNotFound)

I think the setting loads just fine the way I had it. The problem seems to be you have to do some other step to extract the string. The reason I say this is I can call @new_window.to_s() and then use that as my caption to see what I am getting. When I do I get this :

#<Proc:0x00006bfe4e40e8c8@/home/user/rails/redmine/vendor/plugins/test/init.rb:19>

I can then also pass this next line as my caption and it will correctly display the setting of 0 or 1 but it has been passed though menu_manager.rb's if statement and thus converted.
:caption => Proc.new { get_string.call('new_window') },

I can say if @new_window.class == Proc and it will return true. So @new_window is not a string but a proc. That is why when you pass a proc as the :caption Redmine's menu_manager.rb will call

if @caption.is_a?(Proc)
c = @caption.call(project).to_s
c

I am guessing this gives you the string. However, I can't seem to make a similar call to get my string.

Thanks again for your help.

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Sorry I made a mistake above it should read :

I have found I need to use this on that line

if Proc.new { Setting.plugin_menu_link['new_window'] == "0" 

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Proc is ruby's anonymous function class.
And to call the function, you should send the object "call", or "[]".
("[]" is an alias method of "call")

like this

if Proc.new { Setting.plugin_menu_link['new_window']}.call == "0" 

See the ruby referrence for further information
http://ruby-doc.org/core/classes/Proc.html

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Redmine::PluginNotFound (Redmine::PluginNotFound)

The above exception means that the plugin has not been registered yet.
Make sure that the plugin registration is done before you read the plugin settings.
You can check if the plugin registration is done by this line.
If the plugin is not registered, the above exception will be raised.

Redmine::Plugin.find('menu_link')

This line gives you the plugin object that defines the plugin name , url, description, version, settings, menu, etc.
You can change the plugin object after the plugin registion is done like this

Redmine::Plugin.find('menu_link').name "foo" 
Redmine::Plugin.find('menu_link').menu(:top_menu, 
  :link,
  "http://www.google.com",
  :caption => Proc.new { Setting.plugin_menu_link['link_item_name'] }

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Thanks for the tips. However, I am still at the first step. When I enter :

if Proc.new { Setting.plugin_menu_link['new_window']}.call == "0" 

I get
undefined method `plugin_menu_link' for #<Class:0x68ea29a6a398>

As for the rest of it I am just not sure it matter if I can't get past the if statement.

I have attached a zip file with the plugin. As you can see it throws an error on most all of this. Please check my post above and you will see what I mean. change your caption etc and call to sting. you will get the proc thing.

Thank you so much for responding to my post and helping me!

menu_link.zip (2.07 KB)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

You will have to go to settings and save the settings first for the plugin to work.

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

The plugin registration is not done until "Redmine::Plugin.register" executed.
See

# Not Registered yet
Redmine::Plugin.register :menu_link do
  name 'Menu Link Plugin'
  author 'Tide'
  description 'A plugin which adds a link to the top menu of Redmine.'
  version '0.0.1'
# Not Registered yet
  settings :default => {
    'link_item_text' => 'http://www.redmine.org',
    'link_item_name' => 'Example Link',
    'new_window' => '0'

  }, :partial => 'settings/menulink_settings'
# Not Registered yet
end
# Registered!!! You can call Setting.plugin_menu_link.

I modified your init.rb
Please try it

init.rb Magnifier (887 Bytes)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Hey Yuki,

That seems to work. The problem is that only gets loaded when Redmine restarts. Not your fault or even possibly the code. I am not sure how but I can change the name at any time in settings. However, I can not change the new window setting. I can change it but for the settings to take effect I have to restart Redmine.

Is there any way to get this to where I can change the new_window setting and not have to restart Redmine?

Thank you so much for your time Yuki!!!!!

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

To be clear you can change the name setting at any time. However, the new_window setting can only be applied with a Redmine restart.

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

How is it that my setting new_window requires a restart and changing :caption does not require a restart?

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

I understand your problem.
Use the view hook to reflect the plugin settings.

I modified the init.rb, and I think this is what you want.

init.rb Magnifier (966 Bytes)

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Sorry
fixed the hook class name(AccountListener -> MenuListener)

init.rb Magnifier (963 Bytes)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Wow Yuki,

Thank you so much. I can't believe you got it working! I would have never figured this one out.

We ended up at this point in a different manner than I was anticipating. Now I have one thing left.

You can't send a proc as the link right now. If you look at the menu_manager.rb I have attached you will see I added a couple of lines. If you add these you can send a proc as the link itself. What this does is let me change the link on the fly. However, I would prefer to convert the setting to string and send it to the menu manager if I can. If so I would not have to modify or suggest modification to menu_manager.rb.

I have included two versions of the plugin. One that makes you hard code the link and requires no Redmine patch. The second requires the Redmine be patched with my menu_manager.patch and the link can be changed at run time.

If anyone has a suggestion on how to read the link_text setting at run time without having to modify Redmine I would appreciate it.

Yuki, If you do not mind I want to add you to the authors section as you have been a huge help!!

Future options if possible:
- Require user to be logged in option - ?
- Multiple links - ?

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Sorry I just noticed the examples zip above is empty. Here is a new zip file with both examples.

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Jake Tanner wrote:

If anyone has a suggestion on how to read the link_text setting at run time without having to modify Redmine I would appreciate it.

You don't have to midify Redmine core to read the link_text setting at run time.
We can override the method of the menu object by using ruby's singleton method like this.
(But the solution is so dirty that you have to be careful!)

Yuki, If you do not mind I want to add you to the authors section as you have been a huge help!!

Thanks.
I would be pleased to be your plugin's authors.

Future options if possible:
- Require user to be logged in option - ?
- Multiple links - ?

I think it would be nice that the plugin can make multiple links.

init.rb Magnifier (1.03 KB)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

It works but I need to pass a proc for the link (this requires editing menu_manager.rb). I can change the link without these changes if I am going to have to edit menu_manager.rb. I am just trying to avoid this as we would have to wait for Redmine core to implement these changes before we could really release the plugin (assuming they would add the changes).

Do you think there is a way to change the link after we pass a static link? Can we read our setting and pass it a string at the beginning?

RE: How to get a string from Proc.new - Added by Yuki Kita about 9 years ago

Jake Tanner wrote:

It works but I need to pass a proc for the link (this requires editing menu_manager.rb).

I think that you don't have to edit menu_manager.rb to pass a proc for the link.
I overrided the menu url to call the proc by singleton method like this.

menu = Redmine::MenuManager.map(:top_menu).find(:link)
def menu.url
  # @url == Proc.new { Setting.plugin_menu_link['link_item_text'] }
  @url.call
end

So we can get it only by editing init.rb.
Isn't this what you want?

menu_link.zip (2.07 KB)

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

Not sure why but it works now. I must have missed something before. Sorry about that.

I am going to play around with adding a "require user to be logged in" setting. Then if I get that done I am going to work on making it handle multiple links. I will let you know what comes of it.

At this point we have accomplished my original goal! Even if this goes no further it is a nice plugin. I will get it cleaned up and released in some form very soon.

I know I need some checks in there to make sure I certain settings are not blank, etc. I am still new to Ruby so this may take a bit.

Thanks again Yuki! You rock!!

RE: How to get a string from Proc.new - Added by Tide _ about 9 years ago

I have set up a github account for the plugin.

http://github.com/Tide/menu_link

I had some trouble trying to add the require user to be logged in option. There is not a method for setting the condition like we did the html_options.

I am just going to work on adding in some checks and releasing the plugin as is for version 0.0.1.

1 2 (1-25/28)