In my application I have model "Regulation", form for creating regulations looks like this:
- if %W(edit update).include? action_name
= content_for :heading, t('partners.regulations.edit')
- else
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation] do |f|
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
- if %W(edit update).include? action_name
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
- else
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
In my routes I have:
namespace :partners do
resources :regulations, as: :rental_company_regulation, except: :show
end
My controller looks like this:
module Partners
class RegulationsController < ApplicationController
include Partners::BaseController
load_and_authorize_resource through: :rental_company, singleton: true
before_action :set_breadcrumbs
before_action :set_regulation, only: :new
def new
if #rental_company_regulation
redirect_to edit_partners_rental_company_regulation_path(#rental_company_regulation)
end
add_breadcrumb t('partners.regulations.new')
end
def create
if #regulation.save
flash[:notice] = t('partners.regulations.created')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.new')
render :new
end
end
def edit
add_breadcrumb t('partners.regulations.edit')
end
def update
if #regulation.update(regulation_params)
flash[:notice] = t('partners.regulations.updated')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.edit')
render :edit
end
end
protected
def set_regulation
#rental_company_regulation = Regulation.where(rental_company_id: rental_company).first
end
def set_breadcrumbs
add_breadcrumb current_partner.rental_company.name, :partners_root_path
end
private
def regulation_params
params.require(:regulation).permit(:content_pl, :content_en, :rental_company_id)
end
end
end
Creating resource from scratch works properly. But I went to:
"http://localhost:3000/partners/regulations/4/edit" to edit regulation I have the following error:
undefined method `partners_regulation_path' for #<#<Class:0x0000000242fae8>:0x00000007d9afb0>
I can't solve this problem. What's wrong?
Edit:
Rake routes:
partners_rental_company_regulation_index GET /partners/regulations(.:format) partners/regulations#index
POST /partners/regulations(.:format) partners/regulations#create
new_partners_rental_company_regulation GET /partners/regulations/new(.:format) partners/regulations#new
edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) partners/regulations#edit
partners_rental_company_regulation PATCH /partners/regulations/:id(.:format) partners/regulations#update
Edit2:
I've changed my form too looks like this:
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path
Now I can edit exisiting resource but can't create a new one. When I trying to create the new one I have the following error:
No route matches {:action=>"update", :controller=>"partners/regulations"} missing required keys: [:id]
What's wrong?
as
To simplify user2675613's answer, your error is basically caused by using the as argument in your routes
as: basically allows you to "name" the route:
#config/routes.rb
resources :users # -> users_path
resources :users, as: :members # -> members_path
Error
Your error is as follows:
undefined method `partners_regulation_path'
This basically means you're using a path which doesn't exist. This is because you've used the as: option in your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partners_regulation_path
end
resources :partners do
resources :regulations, as: "test" # -> partners_test_path
end
This is confirmed with your routes:
partners_rental_company_regulation_index
new_partners_rental_company_regulation
edit_partners_rental_company_regulation
partners_rental_company_regulation
Fix
The way to fix this is to remove the as: option from your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partner_regulations_path
end
Alternatively, if you wanted to keep the custom name for your paths, you'll have to change your path references to parental_company_regulation_path
As you can see you in your rake routes your url to edit a regulation is edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) and to create a new one the url is new_partners_rental_company_regulation GET /partners/regulations/new(.:format).
You need to change the way you are using your form here. You can create a partial for all the common fields of form but you need to separate the url part in your form to make a create and update requests.
You can make a partial _form.html.haml with contents:
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
Then inside your edit.html.haml you can have:
= content_for :heading, t('partners.regulations.edit')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
Similarly inside your new.html.haml you can have:
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_index_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
Related
I plan to use snippets in Comfortable Mexican Sofa to store email templates. But is there a way to add a field into a snippet. I would use it to store the subject of the email. Would be good to have also the subject in the cms so that our editors can change it if they feel like it.
By default snippets seem to have only two fields 'Label' and 'Identifier'. And of course the 'Content'. I would like to add also a 'Subject' String into the fields.
Simple Three Step Process:
1:
rails g migration AddSubjectToComfyCmsSnippets subject:string
2:
rake db:migrate
3:
create app/views/comfy/admin/cms/snippets/_form.html.haml with the following content:
- content_for :right_column do
= render 'comfy/admin/cms/files/index'
= render :partial => 'comfy/admin/cms/partials/snippet_form_before', :object => form
= form.text_field :label, :data => {:slugify => #snippet.new_record?}
= form.text_field :identifier, :data => {:slug => true}
= form.text_field :subject
= form.text_area :content, :data => {'cms-rich-text' => true}
= render :partial => 'comfy/admin/cms/categories/form', :object => form
= render :partial => 'comfy/admin/cms/partials/snippet_form_after', :object => form
= form.form_group :class => 'form-actions' do
= form.submit t(#snippet.new_record?? '.create' : '.update'), :class => 'btn btn-primary'
= link_to t('.cancel'), comfy_admin_cms_site_snippets_path, :class => 'btn btn-link'
Now you can reference the subject in your app like so:
Subject: #{#snippet.subject}
Monkey patch to get fixtures working:
create config/initializers/cms_monkey_patch.rb with the following contents:
ComfortableMexicanSofa::Fixture::Snippet::Importer.class_eval do
def import!
Dir["#{self.path}*/"].each do |path|
identifier = path.split('/').last
snippet = self.site.snippets.find_or_initialize_by(:identifier => identifier)
# setting attributes
categories = []
if File.exists?(attrs_path = File.join(path, 'attributes.yml'))
if fresh_fixture?(snippet, attrs_path)
attrs = get_attributes(attrs_path)
snippet.label = attrs['label']
snippet.subject = attrs['subject']
categories = attrs['categories']
end
end
# setting content
%w(html haml).each do |extension|
if File.exists?(content_path = File.join(path, "content.#{extension}"))
if fresh_fixture?(snippet, content_path)
snippet.content = extension == "html" ?
::File.open(content_path).read :
Haml::Engine.new(::File.open(content_path).read).render.rstrip
end
end
end
# saving
if snippet.changed? || self.force_import
if snippet.save
save_categorizations!(snippet, categories)
ComfortableMexicanSofa.logger.info("[FIXTURES] Imported Snippet \t #{snippet.identifier}")
else
ComfortableMexicanSofa.logger.warn("[FIXTURES] Failed to import Snippet \n#{snippet.errors.inspect}")
end
end
self.fixture_ids << snippet.id
end
# cleaning up
self.site.snippets.where('id NOT IN (?)', fixture_ids).each{ |s| s.destroy }
end
end
end
ComfortableMexicanSofa::Fixture::Snippet::Exporter.class_eval do
def export!
prepare_folder!(self.path)
self.site.snippets.each do |snippet|
snippet_path = File.join(self.path, snippet.identifier)
FileUtils.mkdir_p(snippet_path)
# writing attributes
open(File.join(snippet_path, 'attributes.yml'), 'w') do |f|
f.write({
'label' => snippet.label,
'subject' => snippet.subject,
'categories' => snippet.categories.map{|c| c.label}
}.to_yaml)
end
# writing content
open(File.join(snippet_path, 'content.html'), 'w') do |f|
f.write(snippet.content)
end
ComfortableMexicanSofa.logger.info("[FIXTURES] Exported Snippet \t #{snippet.identifier}")
end
end
end
I'm using an approach from Railscast to remotely access a table for dataTables.
This is the start of the code in workorders4_datatable.rb:
class Workorders4Datatable
delegate :params, :h, :link_to, :number_to_currency, to: :#view
def initialize(view)
#view = view
end
def as_json(options = {})
{
sEcho: params[:sEcho].to_i,
iTotalRecords: Workorder.external.count,
iTotalDisplayRecords: workorders.external.total_entries,
aaData: data
}
end
private
def data
workorders.external.map do |workorder|
[
link_to(workorder.id, workorder),
h(workorder.parent.try(:id)),
h(workorder.description),
h(workorder.client.try(:client_name)),
h(workorder.woasset.try(:assetnum)),
h(workorder.type.try(:typecode)),
h(workorder.billmethod.try(:method_name)),
h(workorder.workgroup.try(:group_name)),
h(workorder.employee.try(:employee_full_name)),
h(workorder.wostatus.try(:statuscode)),
h(workorder.expenses.tobill.sum("quantity") * workorder.expenses.sum("unitcost")),
h(workorder.events.tobill.sum("hours")),
h(workorder.events.sum("hours")),
link_to('ADD Invoice', new_invoice_path(:workorder_id => workorder), :class => 'btn btn-primary')
]
end
end
All of it works except for this line:
link_to('ADD Invoice', new_invoice_path(:workorder_id => workorder), :class => 'btn btn-primary')
It causes this error:
NoMethodError - undefined method `new_invoice_path' for #<Workorders4Datatable:0x007f94513588a0>:
Yet, the following works in a different view:
<%= link_to 'ADD Invoice', new_invoice_path(:workorder_id => #workorder.id), :class => 'btn btn-primary' %>
Is there some way I can get it to work?
Have you tried to replace new_invoice_path with #view.new_invoice_path? That might work. The reason is because new_invoice_path should be called in context of the view, but it's being called in context of Workorders4Datatable.
I've seen this pattern in the past as a shortcut:
def v
#view
end
v.new_invoice_path
Controller
class FeedEntriesController < ApplicationController
def index
#search = FeedEntry.search(params[:search])
#feed_entries = #search.page(params[:page])
#app_keys = AppKey.all
end
end
My feed_entries/index.html.erb
<%= link_to "Stared", {:controller => "feed_entries", :action => "index", :search => ['is_star = ?', true] }%>
feed_entries table contain is_star:boolean attribute. So, I just want to pass the parameter is_star == true into the params[:search].
But the above code is not working. Please some one help me.
Try
<%= link_to "Stared", {:controller => "feed_entries", :action => "index", :is_star => true } %?
And then you should be able to access in the controller using params[:is_star]
I have a model which is linking to the show method:
<%= link_to "View Others", :controller => "browse",
:action => "show", :id => #id, :d => "25" %>
Clicking the link gives:
http://localhost:3000/browse/santa-cruz?d=25
Rails gives the error though:
No route matches {:controller=>"browse", :action=>"show", :id=>nil, :d=>"25"}
If I take the extra parameter off everything works.
<%= link_to "View Others", :controller => "browse",
:action => "show", :id => #id %>
Goes to http://localhost:3000/browse/santa-cruz
This page loads and I am getting the correct params[:id]
Any ideas?
Pasted bellow is the show for my controller
def show
if params[:d].nil? then
# Show list of addresses in city.
addresses = Address.where(:slug => params[:id])
profile = []
addresses.each do |ad|
profile << ad.profile
end
unless profile.blank?
#profile = Kaminari.paginate_array(profile).page(params[:page]).per(5)
#title = "Profiles Near " + addresses.first.city
#id = params[:id]
else
redirect_to :controller => 'pages', :action => 'notlaunched', :zip => params[:id]
end
else # :d exists
# show all within :d miles.
addresses = Address.where(:slug => params[:id])
nearby = Address.near("#{addresses.first.fulladdress}", params[:d], :order => :distance)
profiles = nearby.map{ |ad| ad.profile }.uniq
end
end
Here's the Index:
def index
cities = []
states = []
Address.find_each do |ad|
cities << { :city => ad.city, :slug => ad.slug } # slug becomes the :id of show
states << ad.state
end
#cities = cities.uniq
#states = states.uniq
#title = "Browse Cities"
end
I have a view which contain multiple links:
<% a.each do |q| %>
<%= link_to "stock it",
{ :action => "stock",
:qid => q.question_id,
:qur => q.question_answers_url,
:qti => q.title } ,
:remote => true %>
<div id="<%= "stock" + q.question_id.to_s %>"></div>
<% end %>
Each link generate AJAX-request. Here is a controller:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
respond_to do |format|
format.js { render :layout=>false }
end
end
Now return to the view. Each link has a 'div' with unique id='stock'. When user press the link I need to add text to specific div with corresponding id.
I have a stock.js.erb file:
$("#stock<number>").html("some text");
How can I pass div-id to stock.js.erb and how can I use it ?
Common use is to add object.id to your DOM id. That what you exactly did:
<div id="<%= "stock_#{q.question_id}" %>"></div>
Then in your controller you shoud define your question_id or your exact question:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
#question_id = params[:qid]
end
Now it will be shared with your stock.js.erb file:
$("#stock_<%= #question_id %>").html("some text");