Redmine plugin development - ruby-on-rails

I am trying to create a message plugin for Redmine. I have couple of doubts regarding this
How could I send the email in Redmine plugin? Is it possible to
create the mailer inside the plugin? If so what is the command for
creating mailer?
I can able to see this(call_hook) method almost all the
controller files. What is the use of this method?
Thanks in Advance

There are two ways how to do it:
Create new Mailer and inherit it from redmine mailer and just add new methods as you want
Patch redmine mailer and add method for sending your mail
I used second one in my plugin RedmineCRM, you could download it and check in lib/redmine_contacts/patches/mailer_patch.rb
require 'dispatcher'
module RedmineContacts
module Patches
module MailerPatch
module InstanceMethods
def contacts_note_added(note, parent)
redmine_headers 'X-Project' => note.source.project.identifier,
'X-Notable-Id' => note.source.id,
'X-Note-Id' => note.id
message_id note
if parent
recipients (note.source.watcher_recipients + parent.watcher_recipients).uniq
else
recipients note.source.watcher_recipients
end
subject "[#{note.source.project.name}] - #{parent.name + ' - ' if parent}#{l(:label_note_for)} #{note.source.name}"
body :note => note,
:note_url => url_for(:controller => 'notes', :action => 'show', :note_id => note.id)
render_multipart('note_added', body)
end
def contacts_issue_connected(issue, contact)
redmine_headers 'X-Project' => contact.project.identifier,
'X-Issue-Id' => issue.id,
'X-Contact-Id' => contact.id
message_id contact
recipients contact.watcher_recipients
subject "[#{contact.projects.first.name}] - #{l(:label_issue_for)} #{contact.name}"
body :contact => contact,
:issue => issue,
:contact_url => url_for(:controller => contact.class.name.pluralize.downcase, :action => 'show', :project_id => contact.project, :id => contact.id),
:issue_url => url_for(:controller => "issues", :action => "show", :id => issue)
render_multipart('issue_connected', body)
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
receiver.class_eval do
unloadable
self.instance_variable_get("#inheritable_attributes")[:view_paths] << RAILS_ROOT + "/vendor/plugins/redmine_contacts/app/views"
end
end
end
end
end
Dispatcher.to_prepare do
unless Mailer.included_modules.include?(RedmineContacts::Patches::MailerPatch)
Mailer.send(:include, RedmineContacts::Patches::MailerPatch)
end
end

Related

Define Controller for the custom action doesnot seem to work Rails Admin

HI Everyone ,
I have rails admin implemented in my project Now there are couple of thing that I currently stuck at
I want a link (Mark as Publisher) In the list View of my user Controller in the rails admin as ajax link something that is done using remote => true in rails after that where the write the associated jscode and html code for it
for the above custom action "mark_as_publisher" I define the configuration setting like this
Inside config/rails_admin.rb
config.actions do
# root actions
dashboard # mandatory
# collection actions
index # mandatory
new
export
history_index
bulk_delete
# member actions
show
edit
delete
history_show
show_in_app
member :mark_as_publisher
end
Now The Definition of the custom action look like this
require "rails_admin_mark_as_publisher/engine"
module RailsAdminMarkAsPublisher
end
require 'rails_admin/config/actions'
module RailsAdmin
module Config
module Actions
class MarkAsPublihser < Base
RailsAdmin::Config::Actions.register(self)
register_instance_option :collection do
true
end
register_instance_option :http_methods do
[:get,:post]
end
register_instance_option :route_fragment do
'mark_as_publisher'
end
register_instance_option :controller do
Proc.new do
binding.pry
if request.get?
respond_to do |format|
format.html { render #action.template_name}
end
elsif request.post?
redirect_path = nil
if #object.update_attributes(:manager => true)
flash[:success] = t("admin.flash.successful", :name => #model_config.label, :action => t("admin.actions.mark_as_publisher.done"))
redirect_path = index_path
else
flash[:error] = t("admin.flash.error", :name => #model_config.label, :action => t("admin.actions.mark_as_publisher.done"))
redirect_path = back_or_index
end
end
end
end
end
end
end
end
Now the View for the same define in app/view/rails_admin/main/mark_as_publisher.erb look like this
<%= rails_admin_form_for #object, :url => mark_as_publisher_path(:model_name => #abstract_model.to_param, :id => #object.id), :as => #abstract_model.param_key,:method => :post ,:html => { :class => "form-horizontal denser", :data => { :title => "Mark" } } do |form| %>
<%= form.submit "save" %>
<%end%>
The get and post url for mark_as_publisher does come under by controller define above and saving the above form result in error called
could not find routes for '/user/5/mark_as_publisher' :method => "post"
Does Any body has an idea of what I'm missing
Sorry for the delayed reply, but I also came into the exact same issue.
EDIT: I notice you already have this, have you tried restarting your server?
if you add the following it will fix it.
register_instance_option :http_methods do
[:get,:post]
end
The problem is by default Actions only respond to the :get requests.
If you run
rake routes
You will see something along the lines of
mark_as_publisher_path GET /:model_name/:id/mark_as_publisher(.:format) rails_admin/main#mark_as_publisher
https://github.com/sferik/rails_admin/blob/master/lib/rails_admin/config/actions/base.rb#L89

Paypal Express Checkout in Rails3

This issue is about: ActiveMerchant + PaypalExpressCheckout + Rails 3.2
I've been trying to build a Paypal Express Checkout on my Rails 3.2 app. Most of the tutorials out there are outdated so I followed a few then read the Paypal Express Checkout integration guide. I've already set up my Sandobx and my paypal informations.
When I try to process the payment by clicking on my "Buy now" link from my view:
<%= link_to image_tag('http://img36.imageshack.us/img36/249/buttonpaypal.png'),
action: 'checkout', controller: 'orders'%>
I am getting the following error:
This transaction is invalid. Please return to the recipient's website to complete
you transaction using their regular checkout flow.
Return to merchant
At this time, we are unable to process your request. Please return to and try
another option.
--- My Controller:
class OrdersController < ApplicationController
include ActiveMerchant::Billing
def checkout
setup_response = ::GATEWAY.setup_purchase(2000,
:ip => request.remote_ip,
:return_url => url_for('confirm'),
:cancel_return_url => url_for(root_path)
)
redirect_to ::GATEWAY.redirect_url_for(setup_response.token)
end
end
--- My Initializer ActiveMerchant.rb:
ActiveMerchant::Billing::Base.mode = :test
::GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(
:login => "I_PUT_MY_EMAIL_HERE",
:password => "I_PUT_MY_PASS_HERE",
:signature => "I_PUT_MY_SIGNATURE_HERE",
:allow_guest_checkout => true
)
--- My routes: routes.rb:
resources :orders do
# Im not sure why 'get :checkout' by itself doesn't work.
get :checkout, :on => :new
get :confirm
get :complete
end
get "pages/index"
This is the gist: https://gist.github.com/11be6cef6a97632343b9
Can anyone point me to a 'recent' tutorial or help me figure out what I am doing wrong here?
The easiest way is to do as follow:
1.) You must create a paypal test account.
2.) Create a Cart Model:
$ rails g model Cart purchased_at:datetime
3.) In your Cart Model Type:
class Cart < ActiveRecord::Base
def paypal_url(return_url)
values = {
# get it form your http://sandbox.paypal.com account
:business => 'ENTER_THE_SELLER_PAYPAL_EMAIL_ADDRESS',
:cmd => '_cart',
:upload => 1,
:return => return_url,
:invoice => id
}
# These values set up the details for the item on paypal.
values.merge!({
# The amount is in cents
"amount_1" => ENTER_AN_AMOUNT_HERE,
"item_name_1" => ENTER_THE_ITEM_NAME_HERE,
"item_number_1" => 1,
"quantity_1" => 1
})
"https://www.sandbox.paypal.com/cgi-bin/webscr?" + values.to_query
end
end
4.) On the appllication_controller.rb file add this
def current_cart
session[:cart_id] ||= Cart.create!.id
#current_cart ||= Cart.find(session[:cart_id])
end
5.) On your the view where you want the checkout button add this:
# 'products_url' is just the url where you would like to redirect
# the user after the transaction
<%= link_to 'Buy with PAYPAL', #cart.paypal_url(products_url) %>
6.) On the controller show action of the view where you want the checkout add this:
def show
...
#cart = current_cart
end
Thats it! This is a PaypalExpressCheckout without a 'real' Cart since I built this Cart without using a Line Item. But you could add a Line Item to it following the Railscast #141 Paypal Basics http://railscasts.com/episodes/141-paypal-basics
There's a recent tutorial here: http://spin.atomicobject.com/2011/10/24/integrating-paypal-express-with-rails-3-1-part-1/.

Ruby on Rails calling ActiveRecord model from within ActionController plugin module

I've a got a method in ActiveRecord::User:
def create_user_from_json(user)
#user=User.new(user)
if #user.save!
#user.activate!
end
end
And I'm trying to call it in a plugin's module method. The plugin is json-rpc-1-1. Here is the relevant code:
class ServiceController < ApplicationController
json_rpc_service :name => 'cme', # required
:id => 'urn:uuid:28e54ac0-f1be-11df-889f-0002a5d5c51b', # required
:logger => RAILS_DEFAULT_LOGGER # optional
json_rpc_procedure :name => 'userRegister',
:proc => lambda { |u| ActiveRecord::User.create_user_from_json(u) },
:summary => 'Adds a user to the database',
:params => [{:name => 'newUser', :type => 'object'}],
:return => {:type => 'num'}
end
The problem is the code in the proc. No matter whether I call ActiveRecord::User.create_user_from_json(u) or ::User.create_user_from_json(u) or User.create_user_from_json(u) I just get undefined method 'create_user_from_json'.
What is the proper way to call a User method from the proc?
I think this needs to be a class method instead of an instance method, declare it like this:
def self.create_user_from_json(user)
...
end

Rails: Custom template for email "deliver_" method?

I'm building an email system that stores my different emails in the database and calls the appropriate "deliver_" method via method_missing (since I can't explicitly declare methods since they're user-generated).
My problem is that my rails app still tries to render the template for whatever the generated email is, though those templates don't exist. I want to force all emails to use the same template (views/test_email.html.haml), which will be setup to draw their formatting from my database records.
How can I accomplish this? I tried adding render :template => 'test_email' in the test_email method in emailer_controller with no luck.
models/emailer.rb:
class Emailer < ActionMailer::Base
def method_missing(method, *args)
# not been implemented yet
logger.info "method missing was called!!"
end
end
controller/emailer_controller.rb:
class EmailerController < ApplicationController
def test_email
#email = Email.find(params[:id])
Emailer.send("deliver_#{#email.name}")
end
end
views/emails/index.html.haml:
%h1 Listing emails
%table{ :cellspacing => 0 }
%tr
%th Name
%th Subject
- #emails.each do |email|
%tr
%td=h email.name
%td=h email.subject
%td= link_to 'Show', email
%td= link_to 'Edit', edit_email_path(email)
%td= link_to 'Send Test Message', :controller => 'emailer', :action => 'test_email', :params => { :id => email.id }
%td= link_to 'Destroy', email, :confirm => 'Are you sure?', :method => :delete
%p= link_to 'New email', new_email_path
Error I'm getting with the above:
Template is missing
Missing template
emailer/name_of_email_in_database.erb in view
path app/views
Try multipart may that work
def test_email
#email = Email.find(params[:id])
Emailer.send("deliver_#{#email.name}")
part :content_type => 'multipart/alternative' do |copy|
copy.part :content_type => 'text/plain' do |plain|
plain.body = render( :file => "conta.text.plain.erb", :email=>#email )
end
copy.part :content_type => 'text/html' do |html|
html.body = render( :file => "conta.text.html.erb", :email => #email )
end
end
end
Aph, I feel silly. I figured it out:
models/emailer.rb:
class Emailer < ActionMailer::Base
def method_missing(method, *args)
logger.info "method missing was called!!"
recipients "Test <test#test.com>"
body "#{ Email.find_by_name(method.to_s).body }"
end
end
Since the incoming method is basically the name of the record, I can pull the body content stored in the database directly and pass that in as the body of the email, bypassing the templates altogether.
I'd go "up a level"
In other words, use the same view for everyone's email. But in the view, render different text depending on the user_id.
Remember that the view can call the render method.
In my case, I let users upload email templates using the liquid template system. (Google for rails liquid templates.) Using liquid is good since it is safe--users can't include arbitrary ruby code in their templates.
Then my email view renders the liquid template and the customized email is thereby generated.

reuse action mailer template

How do I reuse the same action mailer template for multiple mailer "actions"?
In ActionController, you can do
...
render :action => 'another_action'
I'd imagine the same thing can be done in ActionMailer, but I couldn't seem to find the right method. If it's relevant, I'm on Rails 2.3.2.
Thanks!
You're looking for render_message, there is a good example in the API Docs Multipart Message section - pasted below.
class ApplicationMailer < ActionMailer::Base
def signup_notification(recipient)
recipients recipient.email_address_with_name
subject "New account information"
from "system#example.com"
content_type "multipart/alternative"
part :content_type => "text/html",
:body => render_message("signup-as-html", :account => recipient)
part "text/plain" do |p|
p.body = render_message("signup-as-plain", :account => recipient)
p.transfer_encoding = "base64"
end
end
end

Resources