Hi I am trying to implement subscribe button in vendor site so need to render a subscribe form with hidden attribute for vendor_site_id. The form work fine within the scope of subscription controller but I need to render it in vendor_site/show page as partial _new.html.erb. I couldn't figure out the way to fix this problem at my own can any body suggest me with this problem.
My partial view subscriptions/_new.html.erb
<%= form_for(@subscription) do |f| %>
<div class="field">
<%= f.hidden_field @subscription.vendor_site_id, :value=>"1" %>
</div>
<%= button_tag(type: 'submit', class: "btn btn-primary") do %>
<i class="fa fa-user fa-fw"></i> Subscribe
<% end %>
<% end %>
Now when I render this in vendor_sites/index.html.erb
<h3>This is vendor site with id 1 just for the testing of subscription method</h3>
<%= render :partial => "subscriptions/new" %>
it throws a error which says:
First argument in form cannot contain nil or be empty
which I understood so far is that I need to tell this vendor_site controller about the @subscription from other scope. But I cannot figure out how? My subscriptions class looks like this:
class SubscriptionsController < ApplicationController
def new
@subscription=Subscription.new
end
end
A couple of changes you'll need to make here. One thing I'll recommend before getting into the details is the Rails Guides for Layouts and Rendering (and the Rails Guides in general. The Layouts and Rendering Guide in particular will help you greatly with the VC part of Rails.
Now, on to the details. First, a partial is not a controller action. There is no controller method that corresponds to it. You can go about what you're trying to do in one of two ways, and both ways involve removing the new
method from your subscriptions controller first.
First way: Initialize @subscription
in your vendor site controller
The simplest way (in term of changes relative to what you already have) is to initialize @subscription
in your vendor site controller's index
method. Then, the rendered _new
partial will know exactly what subscription
is.
class VendorSiteController
def index
@subscription = Subscription.new # add this anywhere in the index method.
end
end
Second way: Pass @subscription
as a local to the _new
partial
This way will involve changes to your controller, your view, and your partial. In your controller, you'll still need to make the change I gave above.
class VendorSiteController
def index
@subscription = Subscription.new # add this anywhere in the index method.
end
end
Next, you'll need to make @subscription
a local variable in your form, by simply removing the @
.
<%= form_for(@subscription) do |f| %>
<div class="field">
<%= f.hidden_field @subscription.vendor_site_id, :value=>"1" %>
</div>
<!-- no changes to the button tag -->
<% end %>
Finally, you'll need to pass @subscription
as subscription
to your partial in your index view.
<%= render :partial => "subscriptions/new", :locals => { :subscription => @subscription } %>
While this way involves a lot more changes, it is much more flexible than the first way. For instance, say you want to render more than one new subscription in a page:
<% Subscription.where(condition: true).find_each do |s| %>
<%= render :partial => "subscriptions/new", :locals => { :subscription => s } %>
<% end %>
As another example, maybe you want to use the @subscription
variable name for something other than a new subscription, and you're going to use @new_sub
for a new subscription instead.
<%= render :partial => "subscriptions/new", :locals => { :subscription => @new_sub } %>
Hopefully my answer helps you out! Feel free to comment if you need further clarification, and be sure to check out those Rails Guides!
You can do it by in following way, you need to initialize a @subscription object in index action of vendor_sites controller.
class VendorSiteController
def index
#here your showing list of vendors logic
@subscription = Subscription.new #initialize a Subscription object
end
end
Then you can pass @subscription object to your partial in your index view by following way(For Rails 3)
<%= render :partial => "subscriptions/new", :subscription => @subscription } %>
Haven't checked Joe Kennedy
's answer, so apologies if this touches on what he has written:
Partials
The whole point of a partial
is that's meant to be able to be used in any part of your application. They are not tied to specific controllers, which is especially true as they primarily rely on local variables
to help populate their data
This means if you want to render a partial outside the "scope" of a controller, you just need to be able to send the correct data to the partial, through its local
variables:
#app/views/controllers/your_view.html.erb
<%= render partial: "controller/partial", locals: {variable: @value} %>
A very simplistic example, but hopefully should demonstrate how you can call partials anywhere you want.
MVC
You must also consider the MVC programming pattern, as described here:
The importance of this is that Rails is built using the MVC
pattern - in that the controller
works to manipulate the data
to show in your views, the model
is meant to collect / compile the data
, and the view is just meant to show it
This means the partial
should not be "tied" to a particular controller - it just needs to create the data
available in the views, and as such, you should be more focused on how you can show this data, rather than having to call your partial with a particular controller
Data
To summarise so far - you need can put a partial anywhere, and through the use of the MVC programming pattern, populate it using data from your controller
.
The important thing now is to populate the @subscription
value. This could be done in the view (not recommended), or it could be done using a method in your various controllers:
#app/views/subscriptions/_new.html.erb
<%= form_for(subscription) do |f| %>
<div class="field">
<%= f.hidden_field @subscription.vendor_site_id, :value=>"1" %>
</div>
<%= button_tag(type: 'submit', class: "btn btn-primary") do %>
<i class="fa fa-user fa-fw"></i> Subscribe
<% end %>
<% end %>
#app/views/controller/your_action.html.erb
<%= render partial: "subscriptions/new", partials: {subscription: Subscription.new} %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With