I want to add, update and delete event on my redmine calendar(almost similar to a google calendar).I have installed redmine on a Bitnami stack. But I'm not able to understand the code structure as I do not have proper documentation. Is there anyone who can help me on this.
The below listed code is my calendar controller .
class CalendarsController < ApplicationController
menu_item :calendar
before_action :find_optional_project
rescue_from Query::StatementInvalid, :with => :query_statement_invalid
helper :issues
helper :projects
helper :queries
include QueriesHelper
def show
if params[:year] and params[:year].to_i > 1900
#year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
#month = params[:month].to_i
end
end
#year ||= User.current.today.year
#month ||= User.current.today.month
#calendar = Redmine::Helpers::Calendar.new(Date.civil(#year, #month, 1), current_language, :month)
retrieve_query
#query.group_by = nil
#query.sort_criteria = nil
if #query.valid?
events = []
events += #query.issues(:include => [:tracker, :assigned_to, :priority],
:conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", #calendar.startdt, #calendar.enddt, #calendar.startdt, #calendar.enddt]
)
events += #query.versions(:conditions => ["effective_date BETWEEN ? AND ?", #calendar.startdt, #calendar.enddt])
#calendar.events = events
end
render :action => 'show', :layout => false if request.xhr?
end
end
The below is the calender_helper.rb
module CalendarsHelper
def link_to_previous_month(year, month, options={})
target_year, target_month = if month == 1
[year - 1, 12]
else
[year, month - 1]
end
name = if target_month == 12
"#{month_name(target_month)} #{target_year}"
else
"#{month_name(target_month)}"
end
# \xc2\xab(utf-8) = «
link_to_month(("\xc2\xab " + name), target_year, target_month, options)
end
def link_to_next_month(year, month, options={})
target_year, target_month = if month == 12
[year + 1, 1]
else
[year, month + 1]
end
name = if target_month == 1
"#{month_name(target_month)} #{target_year}"
else
"#{month_name(target_month)}"
end
# \xc2\xbb(utf-8) = »
link_to_month((name + " \xc2\xbb"), target_year, target_month, options)
end
def link_to_month(link_name, year, month, options={})
link_to(link_name, {:params => request.query_parameters.merge(:year => year, :month => month)}, options)
end
end
Below is the view ,show.html.erb
<h2><%= #query.new_record? ? l(:label_calendar) : #query.name %></h2>
<%= form_tag({:controller => 'calendars', :action => 'show', :project_id => #project},
:method => :get, :id => 'query_form') do %>
<%= hidden_field_tag 'set_filter', '1' %>
<fieldset id="filters" class="collapsible <%= #query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
<div style="<%= #query.new_record? ? "" : "display: none;" %>">
<%= render :partial => 'queries/filters', :locals => {:query => #query} %>
</div>
</fieldset>
<p style="float:right;">
<%= link_to_previous_month(#year, #month, :accesskey => accesskey(:previous)) %> | <%= link_to_next_month(#year, #month, :accesskey => accesskey(:next)) %>
</p>
<p class="buttons">
<%= label_tag('month', l(:label_month)) %>
<%= select_month(#month, :prefix => "month", :discard_type => true) %>
<%= label_tag('year', l(:label_year)) %>
<%= select_year(#year, :prefix => "year", :discard_type => true) %>
<%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
<%= link_to l(:button_clear), { :project_id => #project, :set_filter => 1 }, :class => 'icon icon-reload' %>
</p>
<% end %>
<%= error_messages_for 'query' %>
<% if #query.valid? %>
<%= render :partial => 'common/calendar', :locals => {:calendar => #calendar} %>
<%= call_hook(:view_calendars_show_bottom, :year => #year, :month => #month, :project => #project, :query => #query) %>
<p class="legend cal">
<span class="starting"><%= l(:text_tip_issue_begin_day) %></span>
<span class="ending"><%= l(:text_tip_issue_end_day) %></span>
<span class="starting ending"><%= l(:text_tip_issue_begin_end_day) %></span>
</p>
<% end %>
<% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %>
<% end %>
<% html_title(l(:label_calendar)) -%>
This is the only code related to calendar in routes.rb
get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar'
get '/issues/calendar', :to => 'calendars#show'
In this controller you have only show action (HTTP GET). If you want update and delete you are supposed to add methods and logic for them gere. You will also need routes in config/routes.rb.
I would also recommend you to take a look into other controllers since this one looks more like a renderer of the calendar and nothing more. I don't see create action as well (HTTP POST) which means you create the entity somewhere else and update and delete are supposed to be there as well (if they are not defined already).
Related
I am trying to make a form for storing data hierarchy through the associations.
My structure of database is
meta
- ID (PK)
version
- meta_id (FK of meta)
- ID (PK)
- lang (FK from lang ...)
- ....
data
- ID (FK of version)
I need to store multiple language content under one ID.
Models are
class Meta < Sequel::Model(:link_meta)
one_to_many :version
end
class Version < Sequel::Model(:link_version)
one_to_one :meta, key: :meta_id
one_to_many :data, key: :id
one_to_one :lang, key: :lang
end
class Link < Sequel::Model(:link)
plugin :timestamps, :create => :created, :update => :updated
many_to_one :version, key: :id
end
And my form for creating input is.
<% form_for :links, url(:links, :create), :class => 'form-horizontal' do |f| %>
<%= partial 'links/form', :locals => { :f => f } %>
<% end %>
And this is my partial
<% f.fields_for :version, :class => 'form-horizontal' do |cz| %>
<%= cz.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% cz.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... form content
</fieldset>
<% end %>
<% f.fields_for :version, :class => 'form-horizontal' do |en| %>
<%= en.hidden_field :lang, :value => Lang.select(:id).where(:lang => "cz").map(:id) %>
<% en.fields_for :data, :class => 'form-horizontal' do |link| %>
<% error = #links.errors.key?(:url) && #links.errors[:url].count > 0 %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
... another form content
</fieldset>
<% end %>
<% end %>
But it fails on
undefined method `data' for [:class, "form-horizontal"]:Array
I tried different association combinations etc, I feel lost.
Thanks
Levi
I am getting undefined method 'session_path' for #<#<Class:0x9859218>:0x8ebcbd0> when using devise with my custom controller and view, can anybody shed some light on what I have done wrong?
routes:
devise_for :users, :skip => [:sessions]
as :user do
get 'account/login' => 'account#login', :as => :new_user_session
post 'account/login' => 'account#login_user', :as => :user_session
delete 'account/logout' => 'account#logout', :as => :destroy_user_session
end
controller:
AccountController < Devise::SessionsController
def login
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
def login_user
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_flashing_format?
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
def logout
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_flashing_format?
yield if block_given?
respond_to_on_destroy
end
view:
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<ul>
<li>
<%= f.label :login, "Email", :class => labels %>
<%= f.email_field :login, :autofocus => true, :class => "wideinput" %>
</li>
<li>
<%= f.label :password, :class => "labels" %>
<%= f.password_field :password, :autocomplete => "off" %>
</li>
<li class='button'>
<%= submit_tag "Login", :class => "btn1" %>
</li>
</ul>
<% end %>
Try to change this line
post 'account/login' => 'account#login_user', :as => :user_session
to
post 'account/login' => 'account#login_user', :as => :session
In liquid templates this is achieved like so:
{{ product.metafields.book.author }}
Which returns the value of 'author' for it's key 'book'
I'm using Shopify API and Ruby on Rails and have successfully looped over each metafield for a given product:
In the controller:
#products = ShopifyAPI::Product.find(:all, :params => {:limit => 10})
In the view:
<% #products.metafields.each do |metafield| %>
<%= metafield.key %> : <%= metafield.value %>
<% end %>
This returns all of the metafields for a product, as expected. How do I return only those metafields matching a specific key i.e. 'book' from the example above?
# add metafield
product = ShopifyAPI::Product.find(product_id)
product.add_metafield(ShopifyAPI::Metafield.new({
:description => 'Author of book',
:namespace => 'book',
:key => 'author',
:value => 'Kurt Vonnegut',
:value_type => 'string'
}))
# retrieve metafield
author = ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => product.id, :namespace => "book", :key => "author"}).value
More info: http://www.shopify.com/technology/3032322-new-feature-metafields
This seems to do the trick:
<% product.metafields.each do |metafield| %>
<% if metafield.key == "book" %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% end %>
<% end %>
or
<% product.metafields.each do |metafield| %>
<% if metafield.key.include?("book") %>
<%= metafield.key %>: <%= metafield.value %><br/>
<% else %>
<% end %>
This works:
ShopifyAPI::Metafield.find(:first,:params=>{:resource => "products", :resource_id => 94549954, :key => "book"})
ShopifyAPI::Metafield.find(:all,:params=>{:product_id => product.id, :key=> 'book'})
You can get all metafields for a product
#product = ShopifyAPI::Product.find(params[:id])
After that, you can get its metafields
#metafields = #product.metafields
Or if you need just a specific metafield for that product
#metafield = ShopifyAPI::Product::Metafield.find(:all, where: {"product_id = ? AND metafield.key = ?", product.id, "book"})
I want to modify the action (submit) for a form_for helper
<%= form_for(#rating, :as => :post, :url => demo_create_rating_path(#rating)) do |f| %>
<div class="field">
<%= f.label :value %><br />
<%= f.select :value, %w(1 2 3 4 5) %>
</div>
<%= f.hidden_field :article_id, :value => #article.id%>
<%= f.hidden_field :user_id, :value => current_user.id %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description, size: "100x5" %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This is my View and it does not work.
All I want is, that I can redirekt the Action after submit button but then a get this error:
ActionController::RoutingError (No route matches {:controller=>"demo_ratings", :action=>"create", :article_id=>#<Rating id: nil, value: nil, description: nil, article_id: nil, user_id: nil, created_at: nil, updated_at: nil>}):
app/views/demo_ratings/_form.html.erb:1:in `_app_views_demo_ratings__form_html_erb__1912848844925280312_70155649546120'
app/views/demo_ratings/new.html.erb:13:in `_app_views_demo_ratings_new_html_erb__27525029454473720_70155632487040'
What am I doing wrong?
UPDATE
All my funktion that are need by form_for helper:
def new
#rating = Rating.new
#article = Article.find(params[:article_id])
end
def edit
#rating = Rating.find(params[:id])
#article = Article.find(params[:article_id])
end
def create
#rating = Rating.new(params[:rating])
if #rating.save
#article= Article.find(params[:article_id])
puts #article.name
puts #rating.id
#rating.article = #article
puts #rating.article.name
redirect_to demo_rating_path(#rating, :article_id => #article.id), notice: 'Rating was successfully created.'
else
render action: "new"
end
end
def update
#rating = Rating.find(params[:id])
if #rating.update_attributes(params[:rating])
#article = #rating.article
redirect_to demo_rating_path(#rating), notice: 'Rating was successfully updated.'
else
render action: "edit"
end
end
Try this:
<%= form_for(#rating, :as => :post, :url => demo_create_rating_path) do |f| %>
The #rating in the url is providing a nil object id, and you don't have an id yet.
If you want to share the form between create and update, then use the following:
<% form_for(#rating, :as => :post) do |f| %>
For reference, review the output of a rails generated scaffold's _form.html.erb.
In your controller, your are saving the new/ updated record before your processing. The statement if #rating.save should come after #rating.article = #article.
def create
#rating = Rating.new(params[:post])
#article= Article.find(params[:article_id])
#rating.article_id = #article.id
if #rating.save
redirect_to demo_rating_path(#rating, :article_id => #article.id), notice: 'Rating was successfully created.'
else
render action: "new"
end
end
I try a bit of ajax first time but did not get success, i want to render a partial on radio button select using ajax, here is my code :
My script.js:
$(document).ready(function(){
$.ajax({
url : "/income_vouchers/income_voucher_partial?$('form input[type=radio]:checked').val()="+$('form input[type=radio]:checked').val(),
type: "GET",
data: {
type: $('form input[type=radio]:checked').val()
}
});
});
income_voucher.js.erb
$("#payment_mode").append('
<% if params[:type]== 'cheque' %>
<%= escape_javascript render :partial => "cheque" %>
<% elsif params[:type]=='card' %>
<%= escape_javascript render :partial => "card" %>
<% elsif params[:type]=='ibank'%>
<%= escape_javascript render :partial => "ibank" %>
<% else params[:type] == 'cash' %>
<% end %>
');
My from:
<script type="text/javascript" src="/javascripts/voucher.js"></script>
<%= form_for(#income_voucher) do |f| %>
<%= render 'shared/form_error', :object => #income_voucher %>
<div >
<%= radio_button_tag :transaction_type,'cash', :checked => true %>
<%= f.label :transaction_type, "Cash", :value => "cash" %>
<%= radio_button_tag :transaction_type,'cheque' %>
<%= f.label :transaction_type, "Cheque", :value => "cheque" %>
<%= radio_button_tag :transaction_type,'card'%>
<%= f.label :transaction_type, "Card", :value => "card" %>
<%= radio_button_tag :transaction_type,'ibank'%>
<%= f.label :transaction_type, "Internet Banking", :value => "ibank" %>
</div>
<div id = "payment_mode">
<% if params[:type]== "cheque" %>
<%= render :partial => "cheque", :f => f %>
<% elsif params[:type]=='card' %>
<%= render :partial => "card", :f => f %>
<% elseif params[:type] == 'ibank'%>
<%= render :partial => "ibank", :f => f %>
<% else params[:type] == 'cash' %>
<% end %>
</div>
<%= f.submit %>
<% end %>
and here is my controller method:
class IncomeVouchersController < ApplicationController
def new
#income_voucher = IncomeVoucher.new
#invoices = current_company.invoices
#income_voucher.build_payment_mode
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #income_voucher }
end
end
def create
#income_voucher = IncomeVoucher.new(params[:income_voucher])
transaction_type = params[:transaction_type]
payment_mode = nil
if transaction_type == 'cheque'
payment = ChequePayment.new(params[:cheque_payment])
payment.amount = #income_voucher.amount
elsif transaction_type == 'card'
payment = CardPayment.new(params[:card_payment])
payment.amount = #income_voucher.amount
elsif transaction_type == 'ibank'
payment = InternetBankingPayment.new(params[:internet_banking_payment])
payment.amount = #income_voucher.amount
else
payment = CashPayment.new
payment.amount = #income_voucher.amount
end
payment_mode = PaymentMode.new
payment_mode.transactionable = payment
#income_voucher.payment_mode = payment_mode
respond_to do |format|
if #income_voucher.save
format.html { redirect_to(#income_voucher, :notice => 'Income voucher was successfully created.') }
format.xml { render :xml => #income_voucher, :status => :created, :location => #income_voucher }
else
format.html { render :action => "new" }
format.xml { render :xml => #income_voucher.errors, :status => :unprocessable_entity }
end
end
def income_voucher_partial
#payment_mode = PaymentMode.new(params[:payment_mode])
end
end
i can see my view form but when select a radio button nothing is rende. Any help would be appreciated
First of all: choose the method - or you using remote form, or ajax submit. If your want that user choose radio button AND click submit to render use in .html.erb:
form_for(#income_voucher, :remote => true)
remove javascript ajax and change param name in .js.erb to :transaction_type
If you want that user choosse radio button and immidiately render move javascript ajax to radio button change event handler like this
$(your_element).change(function(){
$.ajax(){
url : "/income_vouchers/income_voucher_partial",
data: {
type: $('form input[type=radio]:checked').val()
}
}
});
and remove params setting from directly url - set params in 'data:'
in my js.erb file i did this
$(".gradeU").remove();
$("#abcd").after(
'<%= escape_javascript render :partial => params[:payment] unless params[:payment] == 'cash' %>'
);
and in my script :
$(document).ready(function(){
$("#check").click(function(){
var payment = $('form input[type= radio]:checked').val()
console.debug(payment);
$.ajax({
type: 'GET',
url : "/income_vouchers/income_voucher_partial?payment="+payment,
});
});
});
and i did not render same code in form, thanks