I currently have a page that searched through a listings database. On clicking a selection, the view links to that listing's show page:
<div class="listings_wrapper">
<% #listings.each do |listing| %>
<%= link_to listing_url(listing), class: "listing_link" do %>
<div class="listing">
<div class="picture">
<% if listing.thumbnail != nil %>
<%= image_tag(listing.thumbnail, class: "list_image") %>
<% end %>
</div>
The show page that is currently routed as:
get 'listings/:listing_id', to: 'listings#show', as: 'listing'
which will get me the address
localhost3000/listing/612983618 (arbitrary id)
What I'm trying to do is get the route to display information from the database in the route instead, for SEO purposes:
localhost3000/listing/[address]/[booking_id]
When I try to adjust to
get 'listings/:listing_id', to: 'listings#show', as: 'listing/:address/:booking_id'
I get blocked on loading. I've been looking around stackoverflow at similar answers, but haven't got my head around this problem as of yet. Since the link is pulling the object itself, and the route is pulling the id from that, it would make sense to refer to the :address key instead, but something is clearly missing. Help?
In order to make the URI for listings#show to receive the address and booking_id of the object, then you could move the alias in your route definition to the uri argument, like:
get 'listing/:address/:booking_id', to: 'listings#show'
Now it'll be waiting both attributes. While in your controller if you want to find that specific object from both sent attributes, then you can use find_by:
#listing = Listing.find_by(adress: params[:address], booking_id: params[:booking_id])
#listings = Listing.last(3)
Note this will work, but in case you have more than one record with same address and booking_id, find_by will just return the first one.
Related
I have a notification system in my rails app. On my notifications model I have:
message
user_Id
read
link_path
The following code works great for showing me the notifications for the current user, and then showing me the notifications that are read. I'm looping through each of these records where this criteria is true, and then doing a link_to #link do, and then outputting the whole code.
Basically the whole block I can then click on and it will take me to the proper record. That works like a charm.
The default for all new notifications is :read => false.
However, when user clicks on the link, I'm trying to pass :read => true into that record, so that when I come back that particular notification will no longer show, since it's only showing me :read => false notifications.
What is the easiest way to go about this? I've tried wrapping everything in a form_for and trying to pass this value of :read => true into the record, but I can't get that to work. Thoughts?
Controller
#x = Notification.where(:user_id => current_user, :read => false)
View
<% #x.where(:user_id => current_user).each do |notify| %>
<% #link = notify.link_path %>
<%= link_to #link do %>
<div class="row notifyrow">
<div class="col-sm-7">
<p> <%= notify.message %></p>
</div>
<div class="col-sm-3">
<p> <%= time_ago_in_words(notify.created_at )%> ago</p>
</div>
</div>
<% end %>
<% end %>
What you seem to want to do is to update the read attribute on a particular Notification when the user clicks the link. That's absolutely what a Controller method is for. For example, assuming the route for your notify_link is something akin to get '/notifications/:id', to: 'notifications#show', you'd do the following:
class NotificationsController < ApplicationController
...
def show
#notice = Notification.find(params[:id])
#notice.update!(read: true)
end
end
That updates the read attribute on the record, so when you go back to the main view it will no longer appear in your unread list.
By the way, in your controller you run a query to get all the unread notifications for the current user, and then run where() again in your view. It should be sufficient to just do #x.each in your view.
EDIT
To summarise the comments discussion below, since the linked path doesn't include the Notification object ID, you just need to include it in the query parameters. The Rails-generated URL helpers take a hash (following any parameters required to complete the path) and includes them in the query string. So, something like:
national_race_path(#national_race.id, notify_id: notify.id)
will append the ID as <whatever_path>?notify_id=1234 and it will be accessible in the controller via params[:notify_id]. You'll need to handle what happens if no or invalid ID is passed, etc., but that should give you what you need.
I'm trying to render simple check_boxes in a list of results so users can select on which of these results to get additional content for.
Example model setup (names changed):
UserRequest has_one :response
Response has_many :individual_results
IndividualResult has_one :contact_info
In the UserRequestsController I have a show action, which shows the user_request (duh), response, and its individual_results in a table.
The user should be able to select items (= contact_info) to request additional content for those. For some reason I don't manage to render the check_boxes after days of trying. Basically, I don't really understand where and how to store the array of selected contact_infos and how to pass it to the method that then gets the additional content.
My attempt was:
Create a ContactInfosController (didn't exist before, the user was only creating and showing her requests up to now, so contact_info was "model only" before)
Create a method request_content(contact_infos) (as post, to pass the user-selected contact_infos to. If I were to make it Restful, it would probably be "edit/update")
Add the form with check_boxes search_request#show
My search_request/show.html.erb:
<tbody>
<% if #response %>
<% form_for #contact_infos, url: contact_infos_request_content_path(#contact_infos) do |form| %>
<% #response.individual_results.each do |result| %>
# result.foo, ...
# result.contact_info.bar
<%= form.check_box "contact_info", "contact_info.request_content?", "true", "false %>
<% end %>
# form.submit
<% end %>
<% end %>
</tbody>
As it didn't work, I also had to declare the instance variable #contact_infos in RequestsController#show as #contact_infos = #response.individual_results.map { |r| r.contact_info }
Now, it fails at the check_box with "undefined method `merge'". Also, not sure how the params would be passed? I feel I went seriously "off the rails" and probably screwed up the design with this as it seems way too complicated...
Would anybody be so kind and help me get into the right direction, e.g., how would you pass the response to a method to request additional information? Read tons online but somehow couldn't apply it.
Thanks so much!
I've been struggling to get this to work following a tutorial. I've got Users that have profiles, and a Client model that, through a 'many to many' join table, establishes the relationships between the user and the clients.
What I'm trying to do is create a list of check boxes generated from the list of clients in the DB that you can tick on or off, and then when you submit it, the user will have the relationship to those clients through the join table.
It's sort of working with static data as you can see below:
/profiles/show.html.erb
<% #clients.all.each do |client| %>
<li>
<%= check_box_tag "user[client_ids][]", client.id %>
<%= client.client_name %>
</li>
<% end %>
<%= link_to 'Add Clients', '../assign_clients/' + #profile.user.id.to_s , class: 'btn btn-default' %>
Routes
get 'assign_clients/:id', to: 'users#assign_clients'
And finally in my users_controller.erb
def assign_clients
#user = User.find(params[:id])
#user.client_ids = [1,2]
redirect_to :back, alert: 'Assigned Users'
end
Obviously it's just using hard coded values of 1 and 2. What I'm not sure how to do is wrap the checkboxes in the correct form tag/simple_form (which I am using), and then with the 'submit' button, have that do the 'assign_clients' action that passes through the values.
Thank you for any help.
What I'm not sure how to do is wrap the checkboxes in the correct form
tag/simple_form (which I am using), and then with the 'submit' button,
have that do the 'assign_clients' action that passes through the
values.
In order to create a form that will trigger the assign_clients method a route needs to be setup in your routes.rb file like the following:
resources :users do
patch 'assign_clients', to: 'users#assign_clients', as: 'assign_clients'
end
This sets up a route for a user that you can use the http patch method with (ie. UPDATE). The plan is to pass the client_ids to the users controller as params from the form. I gave it a path name so that we can reference it in the form as user_assign_clients_path(:user_id)
Now that we have the route set up...using the default rails form tags you can structure the form along the lines of this:
<%= form_for #user, url: user_assign_clients_path(#user) do |f| %>
<% #clients.each do |client| %>
<li>
<%= check_box_tag "user[client_ids][]", client.id, #user.clients.include?(client) %>
<%= client.client_name %>
</li>
<% end %>
<%= f.submit "Add Clients", class: "btn btn-default" %>
<% end %>
This will create a form allowing you to post the selected clients as an array of ids to the assign_clients method.
Finally, the assign_clients method can then retrieve the client_ids from the params hash (via params[:user][:client_ids] most likely) and update the user instance (retrieved using user_id from params hash also). You will probably have to add client_ids: [] to the end of your strong parameters list for user to whitelist it - but this essentially should behave like a typical update method.
def assign_clients
#user = User.find(params[:user_id])
#user.update(user_params)
redirect_to wherever_path
end
def user_params
params.require(:user).permit(
client_ids: []
)
end
You need to understand several basic concepts, let me explain to you:
on: member routing - in order to solve your issue directly, your route should be something like:
resources :users do
post '/assign_clients/:client_id', on: :member
end
so that other than user_id, the :client_id can be also passed in as a parameter. For the details, you can read about rails guides on routing.
For the checkbox way, you need nested_attributes - http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html. So that you can achieve what u need with a simple update call on users.
You can also implement a customised logic, with the client_ids passed in as parameters. In order to learn how forms & parameters work in rails, you can build a form, submit it, and see how it goes in the rails server log.
If anything is unclear, simply comment below & I'll try to update.
I have ideas controller and static_pages controller. The latter has home action which displays all ideas and which i also use as root path.
I want the user be able to Edit the displayed ideas. So far i have this:
<% if #ideas.empty? %>
<p>Share your ideas! See what people think about it.</p>
<% else %>
<% #ideas.each do |idea| %>
<div class="panel panel-default">
<div class="panel-heading"><%= idea.name %></div>
<div class="panel-body"><%= idea.description %> <br>
<%= link_to 'Edit', edit_idea_path(idea.id) %>
</div>
</div>
<% end %>
<% end %>
I had an issue with an empty idea id which i solved by adding idea.id inside edit_idea_path
Now my question is, is that the proper, Rails way of doing it? In what other way can i fetch the idea object from this index page and use it in my ideas controller instead of static_pages controller?
I tried playing around with routing, but I have very vague understanding of it despite reading the guides and others code. I'd appreciate any insight about this matter.
First you need to understand that the requirement of your project defines what you should do in the code, whithout of concerning about the proper way to do something. You just need to follow the rails conventions.
http://guides.rubyonrails.org/active_record_basics.html#convention-over-configuration-in-active-record
Now, back to your question. You just need to create an action (that will handle a view) in your ideas_controller that will manage the edition of the data sended by de static_pages_controller, i will call it (just for example) edit_static_ideas and receive the data with params:
In your ideas_controller : app/controllers/ideas_controller.rb
def edit_static_ideas
#idea = Idea.find(params[:id])
end
Then you need to create the view in your views->ideas folder. An name it, just to continue my example i'll name it edit_static_idea.html.erb. And set the load of the data you get in #idea as a form or a form_for. Then you can submit that edited data and upload it into other action.
Then you have to configure your routes file and add
config/routes.rb
get 'edit_static_idea/:id', to: 'ideas#edit_static_idea', as: 'edit_ideas'
After that, if you run "rake routes" in your console (inside your rails project), you should see your new route (yay!)
Now you have to take the path in your route and use it in you static_pages_controller's view to redirect it to the edit_idea's view handle it by ideas_controller. And be sure that you also send the id of the selected item.
app/views/static_pages/home.html.erb:
<%= link_to 'Edit Idea', insert_your_edit_idea_obtainedinrakeroutes_path(id: idea.id) %>
At last, you only need to configure the form in your edit_static_idea.html.erb and assign it an upload/save route and redirect it to the view that you want.
for example:
In your routes file: config/routes.rb
patch 'save_edited_idea', to: 'ideas#save_edited_idea', as: 'save_edited_idea'
In your ideas_controller: app/controllers/ideas_controller.rb
def save_edited_idea
#idea = Idea.find(params[:id])
respond_to do |format|
if #idea.update(idea_params)
format.html { redirect_to the_view_that_you_want_path(id: #idea.id), notice: 'Data saved without problems.' }
else
flash.now[:alert] = "error"
format.html { render :offer }
end
end
end
I didn't wanted to be so detailed, because i wanted to help you to understand what you have to do. I hope it helps :P
I'm trying to pass the value of a element to a rails controller!
Currently, I have something like this:
<td id="dbname"><%= link_to db, :action => :show %></td>
This represents a row in an html table, which contains a string value, e.g. "development".
When the user clicks on the "development" link, the <%= link_to ... %> grabs the value from the current clicked and passes that to a rails controller action, in this case the show action.
How can this be achieved!?
UPDATE - generating links:
<% #dbs.each do |db| %>
<tr>
<td id="dbname"><%= link_to db, :action => :show %> </td>
</tr>
UPDATE 2:
this is my index controller:
conn = Mongo::Connection.new
#dbs = conn.database_names #this returns an array of strings (which are the names of the databases)
Now I want to be able to click on of these databases and then to pass the clicked text to the rails controller show action. I'm not sure how I would generate a custom resources path for these links... but I was contemplating of doing it using Ajax or something javascript related. Maybe get the text of clicked link using jQuery and then send an Ajax request to the rails controller with the text as a parameter!
I think that it's a strange thing what you're trying to do, but a solution could be to use javascript to append the id to the href of each link as a query string.
If you could explain a little bit what you're trying to achieve maybe we could find a better solution.
Hope it helps!
Edit:
If you have a table of links I think that you should consider them as a resource and managing them the REST way.
Your controller should have an index and show action and you should declare the links as a resource in the routes file (maybe link it's a reserved word and you will have to use a different name, I'm not sure), the index action will fetch all the links and when you render them, you could specify the link for each one with something similar to "link_path(link.id)" (remember, you should have a show action defined) in the controller you will receive the link id so you could load it with a simple "find" and pass it to the view.
I recommend you to always look for the REST way to solve a problem in ROR.
Edit 2:
Ok let's see if this works for you:
I suppose that you have a model that represent those links that you're talkin about, for example:
class DataBaseLinks < ActiveRecord:Base
end
This model with be backed up by a table in your database, if you have generated it the rails way, you will also have an id column that identify each database link.
in your controller, let's say DataBaseLinksController, you'll have:
class DataBaseLinksController < ApplicationController
def index
#dabatase_links = DataBaseLink.all
end
def show
#database_link = DataBaseLink.find(params[:id])
end
end
(I've avoided all the validations and checks).
All you have to do in your index.html.erb is:
<% #database_links.each do |database_link| %>
<%= link_to database_link.name, database_link_path(database_link.id) %>
<% end %>
This will generate all the links with the correct path to the show action (maybe the route helper is a little bit different, but not so much).
Notice also that you'll have to add into your routes.rb the following line:
resources :database_links, :only => [:index, :show]
How do you see it?
Edit 3:
(I'll delete all my edited answers when we find a correct one)
Ok I'm going to suppose that you are not using something like mongoid so you don't have active record similar objects.
Have you tried this in your view:
<% dbs.each do |dbs_name| %>
<%= link_to dbs_name, :controller => "your_controller", :action => :show, :dbs_name => dbs_name %>
<% end %>