rails trouble with nested resources and routes - ruby-on-rails

I've been using the
to_param
username
end
in my user model so that I can access users by /user/username (instead of ID)
I'm trying to make links to user listings (listings is a nested resource) with:
#listings represent a query on the Listing model
<% #listings.each do |listing| %>
<%= link_to 'Show', user_listings_url(listing.user_id, listing) %>
<% end %>
But its giving me the user_id instead and I tried querying the listing.user_id into the users model but it just returned and object and I can't get the simple user/username/listing path to work :/ Any help? Should I not be using to_param?

try this:
<% #listings.each do |listing| %>
<%= link_to 'Show', user_listings_url([listing.user, listing]) %>
<% end %>
this will link to /user/username/listings/listing_id

Related

Scope of each on rails template

I'm new to rails and I'm trying to build a view that will list the parents and related children
Ex:
Passport has many Visas
I want to list information about the passport and the visas that the passport has.
So I have
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<% end %>
<% end %>
I'm getting the error
undefined method `visa_type' for #Passport:0x000000091b8b28
It looks like rails is trying to find the property visa_type for passport, instead of in visa. How does the scope work within each? Can I force it to access visa_type from visa?
I think you're looking for the fields_for form helper. This will allow you to create fields for the relevant visa attributes. Replace your code sample with the following, and you should be all set.
<% #passport_list.each do |passport| %>
# passportFields
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
You can also iterate over the list as follows:
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
<% end %>
For more information on fields_for, check out the link I added above, and to customize further for your use case, check out the "One-to-many" section.
IMO you should always handle the null case of an object.
Something like this if you use rails (present? is a Rails function)...
<% if #passport_list.present? %>
<% #passport_list.each do |passport| %>
passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<%end%>
<%end%>
<% else %>
<p>Nothing to see here</p>
<% end %>
However if your #passport_list is backed by an ActiveRecord Query, you can handle this in the model/helper/controller by returning the .none query on the model. Note that this differs from an empty array because it is an ActiveRecord Scope, so you can chain AR queries onto it
# scope on AR model
def self.awesomeville
where(country_of_origin: "awesomeville")
end
# method queried in controller
#passport_list = Passport.all
if #passport_list.present?
#passport_list
else
Passport.none
end
# additional filtering in view is now possible without fear of NoMethodError
#passport_list.awesomeville
Whereas a ruby Array would raise an error as it would respond to the Array methods.

Without an action in controller how does rails execute the view?

I just started learning rails. I have a doubt in the following section.
Controller:
book_controller.rb
class BookController < ApplicationController
end
View:
list.html.erb
<% if #books.blank? %>
<p>There are not any books currently in the system.</p>
<% else %>
<p>These are the current books in our system</p>
<ul id="books">
<% #books.each do |c| %>
<li><%= link_to c.title, {:action => 'show', :id => c.id} -%></li>
<% end %>
</ul>
<% end %>
Router:
get 'list' => 'book#list'
When I goto localhost:3000/list, it displays the content of list.html.erb. How does that happen when I don't have an list action in Controller? How is my understanding wrong?
If the #books is defined in the book controller there is no trouble executing this code since the list.html.erb is already define inside the books folder and the route is set as
get 'list' => 'book#list'
Ruby MVC structure is integrated such that when you create a variable #varibale it is already available at view.

Render Restforce::Collection

I am using the restforce gem and I have had success pulling the restforce collection and rendering the first user in the collection.
#users = client.query("select Id,Name from User where Id != ''")
# => #<Restforce::Collection >
#user = #users.first
I am stuck on what seems to be a pretty basic problem. I cannot seem to create a view with a partial to iterate through the collection and show a list of all the users my query has returned. See view below:
<ul class="users">
<%= render 'user', collection: #users %>
</ul>
See partial below:
<%= #user.Name %>
Not a lot going on here, just looking for a basic way to show a list of the user's names.
You could just iterate the collection.
<% #users.each do |user| %>
<ul class="users">
<li><%= user.Name %></li>
</ul>
<% end %>
If you really need to, you can still use a partial like <%= render 'user', user: user %>

Devise - how to show user's post

I use Devise gem for authentication.
In database I have users table and posts table in my database schema (and Post controller).
In post controller I want to find all posts assigned to specific user. I have user_id in posts table.
How to get all user's posts or how to check if specific post is assigned for SIGNED IN user.
I thought about something like this (of course is only pseudocode:
current_user.id == Post.where(params:[post_id]).user_id
So how to get current user id in Devise and how to check the current user id is the same like eg. user_id assigned to viewing post (I want to add 'edit' function when current user is post owner) and how to find all post which current user is owner.
Associations
Firstly, your user_id column in your posts table is what's known as a foreign_key
Foreign keys are used in relational database systems to give you the ability to call associative data from a single record. Simply, it means that you'll be able to use the ActiveRecord associations to call the data you require, rather than having to call it individually:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
end
#app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
This will give you the ability to use the following call:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = current_user.posts
end
end
You'll be best served looking up the has_many association:
Fix
In regards to showing your posts for your users, you need to be sure that you have the correct "flow" set up. What I mean is you need some condition to know whether your user is signed in & that #posts is set:
#app/views/posts/index.html.erb
<% if #posts.present? %>
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
Maybe this is the first time you use Devise. You can access current_user inside controllers or views. I imagine you could do something like this
In controller (posts_controller.rb):
#posts = current_user.posts
In view (posts/show.html.erb, I guess):
if current_user.id = #post.current_user
#render something here
end
Get all post which current user is owner.
#posts = Post.where(:user_id => current_user.id)
and on your view
<%-# commented : checking if #posts is empty -%>
<% if #posts.empty? %>
<span>Sorry, post is empty </span>
<% else %>
<%= #posts.each do |p| %>
<% if p.user_id == current_user.id %>
<% link_to "edit", edit_path(p) %>
<% end %>
<% end %>
<% end %>
There are many ways you could get current_user posts. I'll go the long way.
we need
an action
an action view and a partial
a route
a link_to
* action *
def my_posts
#posts = current_user.posts.all.order(created_at: 'DESC')
end
* view *
my_posts.html.erb
<% if #posts.present? %>
<%= render 'posts' posts: #posts %>
<% else %>
<h1>You don't have any posts yet! create one</h1>
<% end %>
_posts.html.erb
<%posts.each do |post| %>
<%= post.title %>
<% end %>
index.html.erb
<%= render 'posts' posts: #posts %>
route
get 'post' => 'posts#my_posts', as: :my_posts
link_to
<%= link_to 'My posts', my_posts_path %>
I may be late but someone can find it useful :)

Cannot manage associations in Ruby on Rails

I have a Post model which is used to store content posted by guest users, and that content is managed by an Admin user. The admin has the rights to block or unblock a particular post.
What I want to do is this:
Display all unblocked Posts to the Guest Users.
Display all Posts to the admin user.
For the first requirement, I have a model BlockedPost which has a polymorphic association with Post model. The post that will be blocked by the admin will be maintained in the BlockedPost model.
For the second requirement I have to give admin the right to block or unblock any particular content. So in my posts/index.html.erb I have done this
<% #posts.each do |post| %>
<% post.content %>
<% if post.post_blocked? %>
<td><%= link_to 'Unblock', blocked_post_path(content.id),:method => :delete%></td>
<% else %>
<td><%= link_to 'Block', create_blocked_post_path(content.id) %></td>
<% end %>
<% end %>
The post_blocked? method above is defined in the Post model:
class Post < ActiveRecord::Base
def post_blocked?
!self.blocked_posts.nil?
end
end
This works but the problem is every time the post_blocked? method is called it makes a database call.
Is there any way to stop this behavior and get the status of all posts in one database call itself?
hmm... i think you should change your models a little, because they are unconfortable a bit and there isnt any fast way to get your posts from DB,
delete BlockedPost model
and add a column to Post model (in migration)
t.boolean :blocked, :default => true
I'd do it like this:
#blocked_posts = Post.where( :blocked => false)
#unblocked_posts = Post.where( :blocked => true )
or prepare scopes in your Post model
and then in your view just display 2 lists
<% #unblocked_posts.each do |upost| %>
<%= upost.content %>
<%= link_to 'Block that post', ... %>
<% end %>
<% #blocked_posts.each do |bpost| %>
<%= bpost.content %>
<%= link_to 'Unblock', ... %>
<% end %>

Resources