In my Rails 3 application I have a simple model relationship which is as follows:
Animal Model
has_many :claims
Claim Model
belongs_to :animal
has_many :payments
Payments Model
belongs_to :claim
The claim table has a column called animal_id and the payments table has a column called claim_id.
I can successfully list all payments owned by a claim.
What I am trying to do is add a link within the animal show view that creates a new claim with the animal_id already set and the same with the claim show view for the new payment link.
From what I have read you can manually create a link_to with the controller and action set, like so:
Claim Show View
<%= link_to 'Create a Payment', {:controller => "payments", :action => "new", :claim_id => '#claim.id'} %>
This doesn't seem to work, although it does correctly link to the new payment page.
Is there a simpler way?
Off the top of my head, and untested, I think the following would work:
= link_to 'Create Payment', payments_path(:payment=>{:claim_id=>#claim.id}), :method => :post
Adding a hash inside the url helper is just going to put params on the url, which will be interpreted by rails the same way "normal" params posted from a form are.
This will be equivalent to submitting a new payment form, so it will redirect the same way that would. If you want it to be handled via ajax just add :remote => true, and be sure your the create action on your PaymentsController responds to javascript correctly.
Update: Read your question again, you want the new payment form with the claim_id already set?
Ok, there are many ways you could do this. If you pass params to the new action you can take the claim_id from the params, the same as I showed above for creating a record:
= link_to 'New Payment', new_payment_path(:claim_id=>#claim.id)
This should link you to /payments/new?claim_id=123
Then in your controller:
def new
#payment = Payment.new(:claim_id => params[:claim_id])
end
However, as was pointed out in the comments, the better way to do this is to nest payments under claims:
In your routes:
resources :claims do
resources :payments
end
In your PaymentsController:
before_filter :load_claim
def new
#payment = #claim.payments.build
end
def create
#payment = #claim.payments.build(params[:payment])
...
end
private
def load_claim
#claim = Claim.find(params[:claim_id])
end
In your link:
= link_to 'New Payment', new_claim_payment_path(#claim)
Just be aware that now your payment path helpers will need claims in them, ie:
= link_to 'Payment', claim_payment_path(#claim, payment)
Same thing for form helpers:
= form_for [#claim, #payment] ...
Related
I have models User, Event, Rsvp. I want to have a Rsvp form appear in the show page of my Event model. A User can create many Events but I don't need to know which User create which Event (at least I don't think). A User can also rsvp to an Event. My models looks like so:
user.rb
has_many :rsvps
event.rb
has_many :rsvps
rsvp.rb
belongs_to :user
belongs_to :event
I think my RsvpsController should look like this:
class RsvpsController < ApplicationController
def new
#user = current_user
#event = Event.find(params[:id])
#rsvp = Rsvp.new
end
end
Now in my show page of an Event I want a form in the sidebar which lets Users rsvp to the Event. I have something like this but it's not quite right. I'm especially not sure what is the first argument that goes into form_for:
form_for [#user, #event, #rsvp], url: {controller: 'rsvps_controller', action: 'create' } do |f|
in my events/show.html.haml I try to render the Rsvp new action like this:
=render template: 'rsvps/new'
but this instead renders an event/new partial
EDIT
I think I know why this render is rendering an Event new partial. Inside Rsvps/new.html.haml I have render 'form'. I also have a _form.html.haml in my Events folder.
EDIT2
rsvps_controller.rb
def create
#rsvp = current_user.rsvps.build(params[:rsvp])
if #rsvp.save
flash[:success] = "You have RSVPed."
redirect_to Event.find(params[:event_id])
else
end
end
since you want to create the reservation for the current user, you should only pass the event to the rsvp create action. for the form, use
<%= form_for Rsvp.new do |f| %>
<%= f.hidden_field :event_id, value: #event.id %>
This should give you access to the event that the current user wants to rsvp. So in your create action of the Rsvp controller, you can build the reservation by using the following code
def create
#rsvp = current_user.rsvps.build params[:rsvp]
if #rsvp.save
...
end
Ok, I've searched high and low, read tutorials, watched videos and I am still not getting any where with this. I've read similar questions here, but questions were more complex or lacked answers - so here goes...
I have models Account and Invoice. When showing an Account, I'd like a link to 'Create new invoice' which relates to that account. (Later I'd actually like a select field to choose an Account when creating an Invoice, but I'll leave that to another excruciation).
Here are my models...
Account:
class Account < ActiveRecord::Base
attr_accessible :name, :invoice
attr_accessible :name, :invoice
has_many :invoices
end
and Invoice:
class Invoice < ActiveRecord::Base
belongs_to :account
attr_accessible :amount_pretax, :amount_total, :date_sent, :project, :status, :tax, :account, :account_id
end
Now, in my /views/accounts/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #account.name %>
</p>
<%= link_to 'New Invoice', new_invoice_path(:account_id=>#account.id) %>
<%= link_to 'Edit', edit_account_path(#account) %> |
<%= link_to 'Back', accounts_path %>
So, what's happening is, when I click on the New Invoice link it shows the new form, with the account field populated with this weird text: #<Account:0x10fe16bc0> and then when I submit the form I get this error:
ActiveRecord::AssociationTypeMismatch in InvoicesController#create
with this statement: Account(#2281084000) expected, got String(#2267210740)
along with this:
app/controllers/invoices_controller.rb:45:in `new'
app/controllers/invoices_controller.rb:45:in `create'
This is what is in the Invoices Controller:
def new
#invoice = Invoice.new(:account_id => params[:account_id])
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #invoice }
end
end
def create
#invoice = Invoice.new(params[:invoice])
....
end
The above is where I think I'm going wrong, but what to put this those lines is beyond me at the moment. I'm totally a beginner, any help to solve this functionality will surely teach me loads.
Thanks for your time.
When you click the New invoice link on the /views/accounts/show page, I suppose that you want that your new invoice belongs to this account.
So in your form, you don't have to let the user choose an account. You can for example replace the corresponding field by a hidden_field:
<%= f.hidden_field :account_id, :value => params[:account_id] %>
Also in the new action of your controller, replace #invoice = Invoice.new(:account_id => params[:account_id]) by #invoice = Invoice.new
Hope this helps.
you did not post the code of your form, but i guess that you are using a text-field for handling the account association. THIS IS WRONG!
if you use a text-field, then rails will try storing it as a string => Account(#2281084000) expected, got String(#2267210740)
you need to use some kind of relational field like a dropdown or whatever to select one of the accounts that are already there.
there are tons of good examples out there, this might help you: http://railscasts.com/episodes/102-auto-complete-association-revised
Study -> has_many Topics -> has_many References
My Model has the following method to access references based on topic ID:
def self.rel_references(topic_id)
Reference.where(:topic_id => topic_id)
end
I am accessing the above in my controller as follows:
#references= Study.rel_references(params[:topic_id])
I need to have a form on the Study model's Show page to access the references based on the topics the user clicks. (A remote form that loads references based on the topic_id). The way I am trying to do this is:
- form_tag rel_references, :id=>"references_form", :method => 'get' do
= text_field_tag :topic_id, params[:topic_id]
= submit_tag "Get references"
However, I am not being able to access the references in my view. Please help me understand what I may be doing wrong here. I am very new to Rails so I might be missing something here. Thanks!
Removing the deprecated Style block helper - and replacing it with = in my form solved this problem for me. My form Now looks like:
= form_tag rel_references, :id=>"references_form", :method => 'get' do
= text_field_tag :topic_id, params[:topic_id]
= submit_tag "Get references"
I have question model which has many options.
In my question controller new action I create five options ready for my user
def new
#question = Question.new
5.times.with_index do |index|
#question.options.build(:order => index)
end
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #question }
end
end
In the view I loop through all options
- form_for(#question) do |f|
.field
= f.label :title, t("question.title")
= show_errors_for(#question, :title)
= f.text_field :title
- #question.options.each do |option|
- f.fields_for :options, option do |o|
.field
= o.label :option, t("question.option_no", { :index => option.order })
= o.text_field :option
= o.hidden_field :order, :value => option.order
.actions
= f.submit t("add_question.create")
My question model looks like this
class Question < ActiveRecord::Base
attr_accessible :title, :options_attributes
belongs_to :user
has_many :options
accepts_nested_attributes_for :options, :reject_if => proc { |attributes| attributes['option'].blank? }
validates :title, :length => { :maximum => 100 }, :presence => true
validate :min_no_of_options
def min_no_of_options
if self.options.size < 3
errors.add_to_base "Must have at least three options"
end
end
end
And my question controller create action
def create
if current_user
#question = current_user.questions.build(params[:question])
else
#question = Question.new(params[:question])
end
if #question.save
redirect_to(#question, :success => t('question.flash_success'))
else
flash.now[:error] = t("question.flash_error")
render :action => "new"
end
end
Now, when I enter only two options in the form and hit the create button the validation prevents the model from being saved. Which is good. But when the create action renders the new action again, only the option fields that I filled are showing up. The three option fields which were left blank have disappeared.
If I replace the "#question.save" in my create action with "false", the behavior is the same. So this suggests that something in the way I create the #question variable in the create action is responsible for throwing away my empty options.
But if I instead remove the :reject_if from my question model the empty options are showing up after a failing question save as expected. (I have a presence validation for the option attribute in my option model) So this tells me that there is nothing wrong in the way I create the #question variable in the create action. It is not throwing away the empty options. So where they are kicked out?
There was one pretty similar question, but the answer in there is not something I would like to do. Though it might be something I have to do.
rails fields_for does not render after validation error on nested form
EDIT
After some more study with rails console I noticed that it truly is the creation of #question variable where the empty options get thrown away. This happens because I have the reject_if defined in the question model. After commenting the reject_if out from the model the empty options were added into the #question variable.
So I guess I need to remove the reject_if and use after_save callback to destroy empty options from the database. This way I will have the empty options going along with the question until the question is saved.
I'm answering my own question because I got the issue solved.
Blank "options" were removed from the "question" because of reject_if in the "question" model. The reject_if statement was applied when the code below was executed, and therefore blank "options" were removed.
#question = current_user.questions.build(params[:question])
I replaced the reject_if with an after_save callback which removes the options which were left blank.
I have in my User view Index page a button_to tag as follows:
<%= button_to "Make Admin", :action => :make_admin :user => user %>
In the User controller i have:
def make_admin
#user = User.find(params[:id])
#changed_user.role = 3
#changed_user.save
end
I get a message about bad routing, but since I'm not interested in changing the view until after the action I don't know how to route this action. Where have i gone wrong?
You need to name the path in your routes:
# routes.rb
get 'your_path' => 'user#make_admin, :as => 'make_admin' # can use post too
# controller
def make_admin
# logic to make an admin
redirect_to(some_other_path, :notice => 'User was made an admin')
end
then, in your view,
button_to 'make admin', make_admin_path
You might also want to make the call remotely, but you'll need to post another question with more information in that sense