I am new to activeadmin / formtastic and I have having a bit of trouble understanding how things work. I read through the documentation on how to create a form using formtastic but I seem to be still running into issues and I am sure its me not understanding how things work.
I am creating a discussions application very similar to a blog application and the end result is that I would like to create an interface for the administrators to add comments to discussions without having to go into the users interface.
My starting point is the discussions view in the admin section presented by activeadmin. I am attempting to work on the add comment form. According to the instructions, I should be able to add a form using
form partial: 'new_admin_comment_form', locals {discussion_comment: DiscussionComment.new}
which then I should create this partial in app/views/admin/discussions folder. I have done that and have entered some arbitrary text to make sure the partial renders and it does. But once I start adding code I am not able to get the form to display.
The current code I am working with is:
<%= semantic_form_for [:admin, discussion_comment] do |f| %>
<%= f.inputs, :body %>
<%= f.actions %>
<% end %>
So a few questions I have that I wasn't able to find in the documentation:
Where do I create instance variables to be used in my form? I have been setting these in the activeadmin files and that is bothering me.
How do I pass params around? I assumed I could do this as normal yet when I try to view them using <%= debug params.inspect %>, it is empty even when I should have at least the id that was in the parent form. Even when using locals: {id: params[:id]}, id is empty in the partial.
What are the best ways to debug why my form is not appearing? Am I able to use regular ERB if worse comes to worse?
You can do this without a custom form. If you stick to the active admin DSL you can use its has_many method. Example here:
http://www.activeadmin.info/docs/5-forms.html
Your Discussion model should look like this
class Discussion < ActiveRecord::Base
has_many :discussion_comments
accepts_nested_attributes_for :discussion_comments, allow_destroy: true
end
Related
<%= form_for [#blog,#blog.comments.build] do |f| %>
<p><%= f.text_area :text, :size => '40x10' %> </p>
<p><%= f.submit "Post Comment" %> </p>
<% end %>
This is handler by comments_controller, but I would like to know the reason, especially for form_for
The form_for creates a form for creation or update of passed object. If the object is not persisted, the associated url will target the creation action. Otherwise the targeted action will the update. form_for can receive many different kinds of parameter to generate the form.
If you check out the Rails url_helpers documentation, you will see that you can do something like:
<%= link_to 'First comment', blog_comment_path([#blog, #blog.comments.first]) %>
This will generate a link to the first comment of the blog with a path like /posts/#post.id/comments/#post.comments.first.id. This also assumes that you have the correct setup on your routes.rb:
resources :blogs do
resources :comments
end
With this, you generate a bunch of paths that you can use to build, for instance, links and forms. Thus, the form_for in your code works similarly. Think of it as a url_helper. You have a #blog and a comment associated to the post(#blog.comments.build). As the comment is not persisted yet, the will generate a form for the creation of comments targetting CommentsController#create. The associated path will be something like /blogs/#blog.id/comments and the HTTP method will be POST.
Also, check these links to get more info:
Rails Routing
Rails Form Helpers
It adds a form with a text box, submit button and some hidden authentication related hidden fields for entering comment.
The comment is added to #blog object with relationship:
has_many :comments
Comment is build by the code if not present by:
#blog.comments.build
So overall you get a form for entering comments in a # blog object. The blog object is necessary in this case and the comment will be automatically combined to the blog entry in proper column in comment record column "blog_id" by default.
This is called Nested Form Relationship, where instead of editing only one record of comment you can combine the parent object also and edit it.
build is basically used to create a structure for object, something like new ( e.g. Model.new). Form action is decided on the basis of given objects. In your case the objects are #blog and #blog.comments.build so the action called will be of either update of Blog controller or Create of Comments Controller..
Hope this helps.
I know I've written it wrong, but I'm looking at the documentation and can't figure out how.
My model is Quote and has three fields, body, attribution, and work, all strings. The form is intended to add a new quote to a page of quotations.
on main/index.html.erb
<%= form_for(:quote, url: {action: 'create'}) do |f| %>
<%= f.text_field :body %>
<%= f.text_field :attribution %>
<%= f.text_field :work %>
<%= submit_tag "Submit" %>
<% end %>
in main_controller.rb
def create
Quote.create(body: params[:body], attribution: params[:attribution], work: params[:work])
end
The form submits, and an entry is saved to the database -- but it's a totally blank entry. I'm not sure why. Help would be appreciated!
Three things:
The way rails forms are supposed to work, you're not meant to get body, attribution, etc independently, they should be wrapped up into a quote object. But...
In your form, your not properly binding an object to the form the way rails expects. You can read more in the documentation here: http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object. You could also generate a fake scaffold rails generate scaffold HighScore game:string score:integer to generate a fake model and see an example of how it's supposed to work. The default scaffolding even has simple examples of how to deal with save errors.
Finally, as #Paven suggested, when you get confused, be sure to look at what's going on in your log - i.e. what params are being posted to your create action. That is always helpful and a good way to diagnose problems quickly.
Your form does't need the action argument. The form_for helper uses ActiveRecord objects to determine the path, meaning as long as you build your object correctly, you won't need to determine your path individually:
<%= form_for #quote do |f| %>
Secondly, you'll want to look at your create method:
#app/controllers/quotes_controller.rb
def new
#quote = Quote.new
end
def create
#quote = Quote.new(quote_params)
end
private
def quote_params
params.require(:quote).permit(:body, :attribution, :work)
end
The problem is you're not sending an ActiveRecord object to your form_for helper. You can read the explanation here:
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc. Conventions in the
generated field names allow controllers to receive form data nicely
structured in params with no effort on your side.
In order to get the form working correctly, you need to be able to provide a valid ActiveRecord object (#variable), which the helper can use to determine the url etc
My code above helps you provide a new ActiveRecord variable, and allows you to use it in the form. This should allow the form_for method to send your data to the create method, which will then create & save an object in the db for you
I am very new to Rails.
I am looking for the most common and 'rails-like' way to display the output of form data. I know that Simple form and Formtastic are good options to write concise code and display input fields in a user friendly manner. However, I am looking for something slightly different, I want to display the data from these forms as output, and I want to do it in a similar and concise manner. I haven't been able to find anything the last few days that I have been searching around so I figured I should ask Stack Overflow.
What do you normally do:
Write custom helpers to be able to write concise code and display the output data?
Use Simpleform/Formtastic, disable the fields, and modify the css to
make it look the way you want?
Is there a common gem that does this? Or perhaps another way I haven't thought about.
First, thanks for the initial responses. I thought I should clarify my question. Since the answers don't quite hit the mark. I already have a show method in the controller, as well as a view template for it. Currently I am displaying each field individually in the form for about 12 fields using form_for. See example snippet below:
<%= form_for(#event) do |f| %>
<div class="row-fluid">
<div class="span6">
<%= render 'shared/error_messages' %>
<%= f.label :title %>
<%= f.text_field :title, :disabled => true %>
<%= f.label :start_date %>
<%= f.date_field :start_date, :disabled => true %>
</div>
</div>
<% end %>
I guess maybe a better question would be, is their an equivalent to form_for method that display data for users, not to edit it but just to read it? It seems like their would be a a standard way to do it that I haven't discovered.
The easiest way to build forms is to use rails g scaffold Example name:string This would generate the Model, Views, Controller, and the necessary database migrations for a Model named Example with a Name attribute that is a string.
You would then use html and css to style the view how you want.
There is a ton of useful info for you on the rails guides here.
Although this question is rather ambiguous, you must appreciate that this functionality is exactly what Rails is built for (submit data & be able to display / manipulate it somewhere else)
Data
The data in an MVC application is bound by one very important factor - a database
If you're submitting data through a form, your goal is to store it in your database, and display it in other views / controller methods
Therefore, the blunt question to your answer is to abide by MVC processes, and save your data to a central repository (database or other), which you can call later:
View
To get your data into your data store, you first need to submit it
The view part of MVC is where you can display your UI, and consequently is where you can put your form. There is a whole tutorial about how to design this here, but for demonstrations' sake, here's an example of how you'd use your form:
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
Controller
The data you input into your view will be sent to your controller on save
The data is sent via the HTML POST method to be read by Rails as a params[] hash. This hash contains all the sent items from your HTML form, and can be used like this:
#app/controllers/posts_controller.rb
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
end
private
def post_params
params.require(:post).permit(:title, :body)
end
Model
The .save method on your newly created Post object, basically tells your model to put the data into your database (or other data store), which you can then pull later (using the .find method or similar)
#app/models/post.rb
Class Post < ActiveRecord::Base
#stuff here
end
It's important to note your models don't store your data, they simply provide an interface (API if you will) to save the data into some sort of data store (namely, a DB)
Models are super important because they allow you to structure & relate your data, creating the ability to deploy really deep & powerful applications
I have a form for a company model:
<%= form_for(#company) do |f| %>
I also have a fields_for section to edit the imports relation:
<%= f.fields_for(:imports) do |builder| %>
Company has_many :imports
and
Import belongs_to :company
I want to use Kaminari for pagination, but the problem is, Kaminari needs a page object returned from the controller like such:
#imports = Import.where(:company_id => current_user.company.id).page(params[:page]).per(50)
This allows me to use the paginate method from Kaminari:
<%= paginate #imports %>
That works, and displays the page links on my form, however, they are obviously not linked to my fields_for block.
My question is, how can I accomplish pagination with a fields_for block?
I need to allow the user to edit a list of Import models, and there will probably be too many to fit on one page which is why I'm trying to paginate. Basically I'm trying to create a spreadsheet like experience for the user.
I don't need to use Kaminari, but I'm on Rails 3.1 and it seemed to be the popular choice.
Thanks for any help on this.
You can use 'fields_for` with a collection of objects as well.
So you can do
<%= f.fields_for(:imports, #imports) do |builder| %>
If that answers your question then you're done! However if you want it to be a 'spreadsheet' like ordeal then maybe not so much.
The problem being that if you do that each time you go to a new page you will lose all your edited imports.
It may be simpler to do this:
Build all the fields_for and hide them.
Then build your own AJAX 'pagination'.
That way when the submit the changes it will pass all the imports and their changes instead of just the current page.
Given
As the User, I am at a nested new vendors/5/reviews/new. In addition to :params that will get written to the Review model, I need to be able to include tags that belong to the Vendor model.
I have used acts_as_taggable_on (http://github.com/mbleigh/acts-as-taggable-on):
class Vendor....
acts_as_taggable_on :tags, :competitors
I use formtastic to submit the tags and field_for to make sure that I write to vendor even though the form is on a CREATE Review:
semantic_form_for ....
<% fields_for :vendor do |vendor| %>
<p>
<%= vendor.label :tags %><br />
<%= vendor.text_field :tag_list %>
</p>
<% end %>
I try to display the tags for the Vendor with the following:
Tags: <%=h #vendor.tag_list %>
My outcome: NOTHING.
1) Am I correctly writing the tags? It looks like it is create the right SQL in the console
2) Am I doing the right approach to display the tag list using acts_as_taggable_on?
First, I'm a bit confused why you're using Formtastic (semantic_form_for) when all of the helpers in the form are standard rails helpers (fields_for, label, text_field), so this really doesn't have much to do with Formtastic.
Second, if the form is for a Vendor record (form_for(#vendor)), then fields_for(:vendor) doesn't make any sense. Using fields_for inside a form_for creates a nested form with nested attributes (useful to create a parent record and an associated record at the same time).
I'd need to see a complete sample of the form code to really get a grip on what you're trying to do, but I think you've over complicated something quite simple. Either way, my advice is to correctly understand form_for before using semantic_form_for.