Passing a parameter between views in Rails - ruby-on-rails

I am trying to accomplish something like this:
I am creating a simple blog. I have set up categories for my blog.
I want that when my user goes to posts/index, he sees a list of all categories.
Example:
Text
Image
Upon clicking on a category, my user gets redirected to the posts/new page, where the category_id field will by transmitted through a hidden_field.
So my code right now is:
in posts/index
<% #categories.each do |c| %>
<%= link_to c.name, new_post_path(:category => c.id) %><br />
<% end %>
and in my posts/_form i'm trying to do something like this
<%= f.hidden_field :category_id, :value => params[:category_id] %>
which is not working though, because the html output is
No value is being passed.
What is the correct way to proceed here?
Thx!

At first glance it looks like a simple mistake mixing up the param names category and category_id.
Try this:
<% #categories.each do |c| %>
<%= link_to c.name, new_post_path(:category_id => c.id) %><br />
<% end %>

Also, from what i can understand in your code, it seems a post belongs to a category. In such case, you could nest routes from one in another, and paths for creating nested object would become accessible, such as new_category_post(#category).
The routing would look like that:
resources :categories do
resources :posts
end
You can read about this matter here: http://guides.rubyonrails.org/routing.html

Related

Passing Input Text From text_field_tag as a variable for a URL...?

Okay, so I didn't know really how to word this correctly, but here is essentially what I am trying to do.
I am trying to take the text that a user inputs into my search box and pass it on to the URL.
Here is my view page so far:
<h1>What's the weather like by you?</h1>
<br />
<%= form_tag('http://api.wunderground.com/api/myAPIkey/conditions/q/**USER_TEXT_FROM_TEXT_FIELD_TAG**.json',:method =>
'get') do %>
<p>
<%= text_field_tag 'zipcode', params[:search] %>
<%= submit_tag "Check It Out!", :name => nil %>
</p>
<% end %>
I know this is probably such an easy thing to do, but I can't seem to find any way to correctly do it. Thanks for your help!
It looks like you are trying to redirect form submission to different url based on user input.
My no JavaScript sugestion would be to go through your own controller and redirect_to custom url. Something like this:
change your view to:
<h1>What's the weather like by you?</h1>
<br />
<%= form_tag('/weather') do %>
<p>
<%= text_field_tag 'zipcode' %>
<%= submit_tag "Check It Out!", :name => nil %>
</p>
<% end %>
create weather controller:
rails g controller weather create
add this line to your config/route.rb file:
match 'weather' => 'weather#create', via: :post
and modify you app/controllers/weather_controller.rb to look like this:
class WeatherController < ApplicationController
def create
redirect_to "http://api.wunderground.com/api/myAPIkey/conditions/q/#{params[:zipcode].split.join('+')}.json"
end
end
This isn't a nice solution and it isn't the smartest solution, it simply duplicates your code using rails stack. Your question doesn't give many information about what you would like to to with the date returned by api?? Do you really want to simply redirect to given url and see data as json?
I just try to give you another idea how to tackle this problem, its not a final solution.

Rails Controllers - Adding a Custom Action

I have an Article resource and have defined resourceful routes for it. I want to create a simple page that shows the articles of the current user. I am aware that it is possible to do so by adding another action, for example 'search' to articles controller which will contain the custom code that searches for articles that have the same user id. And for the routes:
resources :articles do
get 'search'
end
But I'm not sure if adding a custom action is a good idea in this case. I'm thinking I can still use the index action (which shows all articles) and pass some sort of parameter from the url so that it can distinguish if the user wants to see all articles or just his own. But I'm not sure exactly how this can be done. Any help would be great. Thanks!
You can use the query string to pass parameters. see here
So you can pass something like .../articles?user_id=2
In your controller, just change the behavior according to the user_id parameter.
you don't need to create a new action/view for it.
You can add a small form to filter all articles or only my articles, for example:
<%= form_tag articles_path, method: :get do %>
<%= radio_button_tag :search, "all", :checked => true %>
<%= label_tag :all %><br />
<%= radio_button_tag :search, "my" %>
<%= label_tag :my_articles %><br />
<%= submit_tag "filter", name: nil %>
<% end %>
than in your controller:
def index
if params[:search] == 'my'
#articles = current_user.articles
else
#articles = Article.all
end

rails 3.1 select_tag usage

Ive got a select_tag field at the top of a page and trying to get the selected option to change the content on the page based on the users selection.
Im a learner and have found pieces of information around but without detailed examples and good explanations on how to best approach and implement.
The scenario is as follows:
I have a belongs_to association between a project and documents and in one of my views which lists documents, I want to only show all the documents that belong to the currently selected project in the select tag.
Passing the selected project's id to the documents index action which only shows documents for a specified project id via a link_to tag came to mind. This would thus refresh the page with the correct documents in the view but I believe that is not the correct way to do it and that I cant use link_to tags as options in a select_tag. Can anyone help and offer an example?
I would suggest using the form.select method and options_for_select as in
f.select :attribute, options_for_select(#array, default_value)
and in your controller you should create or update using the submitted parameter
n = record.new(:attribute => params[:attribute])
have fun
In your controller:
def index
if params[:project]
#documents = Document.where(:project => params[:project]
else
#projects = Project.all
end
end
In your form/view:
<%= form_tag 'projects', :method => :get do %>
<%= options_from_collection_for_select(#projects, :id, :name)
<%= submit_tag %>
<% end %>
<% if #documents %>
<%= #documents.each do |d| %>
....
<% end >
<% end %>

Rails input from view

In rails how do you get information from view to use in a controller. Like if i have a page with a text field and a button, how would i send the value from the field (without a model) into my controller to work with it in one of my functions. Im using rails 3
Sounds like you could use a simple form, for example:
in your views/products/index.html.erb:
<% form_tag omg_products_path do %>
<%= text_field_tag :my_input %>
<%= submit_tag "Send input" %>
<% end %>
in your controllers/products_controller.rb:
def omg
my_input = params['my_input']
#do whatever you want with my_input
end
You will also want to configure routes.rb, for example like this:
resources :products do
post :omg, :on => :collection
end
I think you will still want a model, but just use a Non Active Record Model see this Rails Cast: http://railscasts.com/episodes/121-non-active-record-model

rails: how to add child association through a text field?

I have two models: Company and Person
class Person < ActiveRecord::Base
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :people
accepts_nested_attributes_for :people, :allow_destroy => true, :reject_if => proc {|attrs| attrs.all? {|k,v| v.blank? } }
end
And my HTML form partial for new and edit actions looks like this:
<% form_for(#company) do |company_f| %>
<p>
<b>Name</b><br />
<%= company_f.text_field :name %>
</p>
<ul>
<%= render :partial => 'person_fields', :collection => #company.people, :locals => {:company_f => company_f} %>
<%= link_to_add_fields(:people, company_f) %>
</ul>
<p>
<%= company_f.submit "Submit" %>
</p>
<% end %>
where "_person_fields" partial looks like this:
<li>
<% company_f.fields_for :people, person_fields do |person_f| %>
<%= person_f.label :name %>
<%= person_f.text_field :name %>
<% end %>
</li>
At the moment, if I typed in person_f.text_fiel :name the name of the person, and hit save, a new Person model with that name gets created. Not what I want at all, I already HAVE that person's Person model in the database, I rather want to ASSOCIATE this person to this company.
Another thing is that I wouldn't mind using the name for human-friendly identification of the person rather than id like this for the "_person_fields" partial
<li>
<% company_f.fields_for :people, person_fields do |person_f| %>
<%= person_f.label :id %>
<%= person_f.text_field :id %>
<% end %>
</li>
this by the way, doesn't work either. when I hit submit, nothing happens. nothing gets saved or changed or anything.
So I thought, just for the sake of experiment, say I did use id's for identification for a Person model, (so that I don't have to go in to autocomplete with a hidden id field which I am using for another project. I hate it). All I want is: go to a new/edit Company page, there's a bunch of textfields for me to type in ids of people, and save and then these people are then associated with the company. I mean, it's exactly like
people = Person.find(1,2,3)
#=>["romeo","juliet","henry"]
company = Company.first
#=>["Shakespeare Co."]
company.people<<people
company.people
#=>["romeo","juliet","henry"]
And it'd be best if I didn't have to use select menus because eventually if the project takes off and I have a thousand people, that's too big for any select menu. I know then I will have to use autocomplete + hidden id field that gets set when a person's name is chosen.
Thanks!!
accepts_nested_attributes_for :people defines people_attributes and people_attributes= methods in your Company model. Those two methods are used when you have fields_for :people in form. As stated in documentation (read whole page, not only method definition):
Nested attributes allow you to save attributes on associated records through the parent.
It doesn't work to associate two objects, that can be done without it, you still have people method in Company.
Formtastic for example uses select with multiple attribute (you can check more than one option with ctrl) or list of check_boxes (easier for normal user, don't have to touch keyboard).
If you want to use autocomplete, it could be done, but you need to append your ids to people[] array (don't remember format right now, I'll check later. You can check its format when you create attribute in your form for :people I think)
Edit:
I think I know hot to do it simple way (without autocomplete, simple html only).
In your companies/edit (or new) view place:
<p>
<%= company_f.label :people %>
<%= company_f.collection_select :person_ids, Person.all, :id, :name, {}, {:multiple => true} %>
</p>
That will allow you to select multiple people to company (with Ctrl). Params generated by this part transfered to your controller should now look like:
"company"=>{"name"=>"CompanyA", "person_ids"=>["1", "3"]}, "commit"=>"Update", "id"=>"4"
If you want to show people with checkboxes I managed to get it with this (I copied part of markup from formtastic):
<ul>
<% Person.all.each do |person| %>
<li>
<%= check_box :person, :id, {:name => "company[person_ids][]", :checked => #company.people.include?(person) }, person.id, nil %>
<%= person.name %>
</li>
<% end %>
</ul>
I had no time today to check how to do it with hidden fields, so you can use autocomplete, but I believe that it should be similar to checkboxes - you need to use something which adds <input type="hidden" name="company[person_ids][]" value="#{person.id}"> for every autocompleted person, and also need to create initial list of people already in company (YOU OVERRIDE THE LIST, not add to list).
If you want field to add or remove (separate fields, sorry) people from company, then this should work:
in Company model:
def add_people=(people_ids)
ids = people_ids.split(/,/).map(&:to_i)
person_ids += ids if ids
end
def add_people
""
end
def remove_people=(people_ids)
ids = people_ids.split(/,/).map(&:to_i)
person_ids -= ids if ids
end
def remove_people
""
end
and in your new/edit view:
<p>
<%= f.label :add_people %><br />
<%= f.text_field :add_people %>
</p>
<p>
<%= f.label :remove_people %><br />
<%= f.text_field :remove_people %>
</p>
Now all you need to do is to find JavaScript for auto-complete, connect it to ids and names of all people (probably PeopleController#index, :format => :json should be good) and tell it to fill those text_fields (can be hidden fields if you would use autocomplete).
This approach should work, because you define virtual attributes in company model, and by assigning to them string in format "1, 2, 6", you add/remove those ids from your collection of associated people

Resources