How do I dynamically change the path_to()? - ruby-on-rails

I currently have three methods which I want to collapse into one:
def send_email(contact,email)
end
def make_call(contact, call)
return link_to "Call", new_contact_call_path(:contact => contact, :call => call, :status => 'called')
end
def make_letter(contact, letter)
return link_to "Letter", new_contact_letter_path(:contact => contact, :letter => letter, :status => 'mailed')
end
I want to collapse the three into one so that I can just pass the Model as one of the parameters and it will still correctly create the path_to. I am trying to do this with the following, but stuck:
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to "#{model_name.camelize}", new_contact_#{model_name}_path(contact, call_or_email_or_letter)"
end
Thanks to the answers here, I have tried the following, which gets me closer:
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
:contact => contact,
:status => "done",
:model_name => model_name) )
But I can't seem to figure out how to past the #{model_name} when it is an :attribute and then send the value of model_name, not as a string, but referring the object.
I got this to work: -- giving points to Kadada because he got me in the right direction :)
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
:contact => contact,
:status => 'done',
:"#{model_name}" => call_or_email_or_letter ) )
end

Try this:
def do_event(contact, call_or_email_or_letter)
model_name = call_or_email_or_letter.class.name.tableize.singularize
link_to( "#{model_name.camelize}", send("new_contact_#{model_name}_path",
contact, call_or_email_or_letter) )
end

Related

Highcharts gem not working

I'm trying to create a line graph of weights for a user off of the lazy high charts gem.
I currently have in my users_controller
def show
#user = User.find(params[:id])
#weights = Weight.where(user_id: #user.id)
#weight_hash = #weights.to_json
#chart = LazyHighCharts::HighChart.new('graph') do |f|
f.title(:text => "Historical Weights")
f.xAxis(:type => 'datetime', :title => {:text =>'Date'})
f.yAxis(:title => {:text => "pounds"})
f.series(:name => 'Weight', :data => #weight_hash)
f.chart({defaultSeriesType => 'line'})
end
end
Within my weight model I have:
class Weight < ActiveRecord::Base
belongs_to :user
def as_json(*args)
{
:weight => self.weight,
:date => self.date
}
end
end
Then in my users/show.html.erb I have
<%= high_chart("Weight", #chart) %>
but i'm getting the error
undefined local variable or method `defaultSeriesType' for
#
I'm not sure how this method should be declared as it is part of the gem. Could anyone please explain what is going on?
In this line:
f.chart({defaultSeriesType => 'line'})
It looks like you forgot to add a colon to defaultSeriesType to make it a symbol, so Ruby thinks it's a variable/method. Try changing it to:
f.chart({:defaultSeriesType => 'line'})
...like the other hashes.

undefined method `each' for "#<Complaigns::ActiveRecord_Relation:0x00000003cfb4c8>":String

I have a model, called Complaign, with some other attributes along with the date of complaign (c_date).
In the ComplaignController, I have an index view, which displays all the complaigns. There is a filter which takes from date and to date. On filtering that, it works fine, and properly displays the complaigns fired on those dates.
Now I want the result of this query to be passed on to a different method, say export method.
I thought of passing this from the index view, since it is stored in #complaigns.
This is my index method:
def index
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
end
In the index view, this is what I have written
<%= link_to "Export", {:controller => "complaigns", :action => "export", :complaigns => #complaigns}%>
This is the export method
def export
#complaigns = params[:complaigns]
end
Now, in the export view, when I do the follwing line:
#complaigns.each, I get this error--
undefined method `each' for "#<Complaign::ActiveRecord_Relation:0x00000003cfb4c8>":String
Now this is because, I think, there is no method each in String class. Is there any way, I can convert the String to Complaign type in the method export or while passing it from the index view, pass it as Complaign object instead of String? Is there any other way of doing this?
You can't pass Ruby on Rails model objects directly in the controller parameters, you can pass their corresponding ids and then load the models from the database. HTTP / Ruby on Rails is stateless. If you always go to index before export, one way how to solve this might be:
<%= link_to "Export", {:controller => "complaigns", :action => "export", :complaigns => #complaigns.map(&:id)}%>
def export
#complaigns = Complaigns.find(params[:complaigns])
end
It looks like #complaigs is passed as string instead of actual active_record relations object. You should calculate #camplaigs in export instead of sending them. Or you can pass array of ids
#complaigns.collect(&:id)
HTTP is stateless protocol, which means each request is independent from the other (unless you use cookie or session). For your export method, it knows nothing about the result of index method unless you pass enough information to it. So a simple solution can be:
index view
<%= link_to "Export", {:controller => "complaigns", :action => "export", :from => params[:from], :to => params[:to] }%>
export method
def export
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
end
Here, the parameters for index is passed to export.
But this method is not DRY enough. You can consider using index for export like this:
def index
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
if params[:export].present?
render 'export'
else
render 'index'
end
end
Then in your export link, you can use this:
<%= link_to "Export", {:controller => "complaigns", :action => "index", :from => params[:from], :to => params[:to], :export => true }%>
PS. These codes are not tested. Just for demonstration purpose.
You can't do what you are trying to do. The problem is that when the view is rendered, the resulting HTML is text, and therefore #complaigns is turned into it's equivalent text (the same as #complaigns.to_s).
To do what you want, you need to pass to your link, the same paramaters you used to create #camplaigns in your index view. So:
Change your link to:
<%= link_to "Export", {:controller => "complaigns", :action => "export", :to => params[:to], :from => params[:from]}%>
And then change your export method to:
def export
index
end

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

Custom Settings Form in ActiveAdmin

I'm using rails-settings by Squeegy from https://github.com/Squeegy/rails-settings as well as Activeadmin. What I'm trying to accomplish is making a form in ActiveAdmin that I can let the site admin change the settings for the site, which take a command line syntax of:
Setting.foo = "bar"
Setting.site_title = "My Awesome Site!"
Setting.max_users = 35
I really don't think I've got too far, but I'm already stuck. I'm up to the point of having a custom ActiveAdmin form made:
ActiveAdmin.register_page "Settings" do
action_item do
link_to "View Site", "/"
end
content do
form do |f|
#Inputs for Settings
end
end
end
But I don't even know how to begin laying out the form to directly access the Settings model, or how to make a custom controller to handle the input. I suppose if I could get the input sent to a controller that I could make, I'd be just fine.
This is very simple to do with ActiveAdmin.
Lets say your settings class is Settings :
ActiveAdmin.register_page "Settings" do
content do
table :class => 'settings' do
thead do
th 'Setting'
th 'Value'
th ''
end
Settings.all.each do |key, val|
tr do
td strong key
td val
td do
link_to "delete", admin_settings_delete_path( :key => key ), :method => :post
end
end
end
tr do
form :action => admin_settings_create_path, :method => :post do
td do
input :name => 'key'
end
td do
input :name => 'val'
end
td do
input :type => 'submit', :value => 'Add'
end
end
end
end
end
page_action :create, :method => :post do
Settings[params[:key]] = params[:val]
redirect_to :back, :notice => "#{params[:key]} added"
end
page_action :delete, :method => :post do
Settings.destroy params[:key]
redirect_to :back, :notice => "#{params[:key]} deleted"
end
end
Of course you'll need to add some CSS and maybe some validations but you have your settings page.
Edit:
Note that I wrote this for rails-settings-cached, not rails-settings, but my quick search led here so I guess this could still help someone.
I don't think you want your site's form to directly change the settings in ActiveAdmin, I would ...
Create a new table, eg. adminsettings and add fields for each of the settings you want to store for instance site_title, alternatively you could use each row for a setting which means you can add new settings in the future without changing the database
Put together a form in Activeadmin to maintain your settings
Add some functions to your model to grab the settings so you can do something like ..
Setting.site_title = Adminsetting.getsitetitle
You could be clever with your model method and use the method_missing facility so you need the least amount of code to get a setting ...
class << self
def method_missing(method, *args, &block)
setting = Adminsetting.where(:code => method.to_s).first
if setting
return setting.content
else
return super(method, *args, &block)
end
end
Perhaps you could package this into a Gem as it could be a useful thing for others.

problem using 'as_json' in my model and 'render :json' => in my controller (rails)

I am trying to create a unique json data structure, and I have run into a problem that I can't seem to figure out.
In my controller, I am doing:
favorite_ids = Favorites.all.map(&:photo_id)
data = { :albums => PhotoAlbum.all.to_json,
:photos => Photo.all.to_json(:favorite => lambda {|photo| favorite_ids.include?(photo.id)}) }
render :json => data
and in my model:
def as_json(options = {})
{ :name => self.name,
:favorite => options[:favorite].is_a?(Proc) ? options[:favorite].call(self) : options[:favorite] }
end
The problem is, rails encodes the values of 'photos' & 'albums' (in my data hash) as JSON twice, and this breaks everything... The only way I could get this to work is if I call 'as_json' instead of 'to_json':
data = { :albums => PhotoAlbum.all.as_json,
:photos => Photo.all.as_json(:favorite => lambda {|photo| favorite_ids.include?(photo.id)}) }
However, when I do this, my :favorite => lambda option no longer makes it into the model's as_json method.......... So, I either need a way to tell 'render :json' not to encode the values of the hash so I can use 'to_json' on the values myself, or I need a way to get the parameters passed into 'as_json' to actually show up there.......
I hope someone here can help... Thanks!
Ok I gave up... I solved this problem by adding my own array methods to handle performing the operations on collections.
class Array
def to_json_objects(*args)
self.map do |item|
item.respond_to?(:to_json_object) ? item.to_json_object(*args) : item
end
end
end
class Asset < ActiveRecord::Base
def to_json_object(options = {})
{:id => self.id,
:name => self.name,
:is_favorite => options[:favorite].is_a?(Proc) ? options[:favorite].call(self) : !!options[:favorite] }
end
end
class AssetsController < ApplicationController
def index
#favorite_ids = current_user.favorites.map(&:asset_id)
render :json => {:videos => Videos.all.to_json_objects(:favorite => lambda {|v| #favorite_ids.include?(v.id)}),
:photos => Photo.all.to_json_objects(:favorite => lambda {|p| #favorite_ids.include?(p.id)}) }
end
end
I think running this line of code
render :json => {:key => "value"}
is equal to
render :text => {:key => "value"}.to_json
In other words, don't use both to_json and :json.

Resources