Issues with nested scaffold's setters - ruby-on-rails

I have 3 scaffolds that resources are nested as following: mangas > chapters > scans. I'm trying to create a website that allows visitors to read mangas chapters, but I'm getting some difficulties to set up the scan_controller's setter.
I have some constraints to follow: the manga scaffold uses FriendlyId, and both chapters and scans are shown to the URL via their chapter/scan number (an integer)
So, for the manga controller, i did the following:
private
def set_manga
#manga = Manga.friendly.find(params[:id])
end
I simply followed the manuel, no problem whatsoever.
For the chapter_controller, I did this
private
def set_chapter
#manga = Manga.find_by(slug: params[:manga_id])
#chapter = #manga.chapters.find_by(chapter_number: params[:id])
end
This allows me to get all chapters that are linked to the manga I want, and only them. Plus, I get to pass the chapter_number as an id into the link.
And, lastly, I tried this for the scan_controller:
private
def set_scan
#manga = Manga.find_by(slug: params[:manga_id])
#chapter = #manga.chapters.find_by(chapter_number: params[:id])
#scan = #manga.chapters.scans.find(params[:id])
end
However, at this point, I can't get a satisfying result. With this configuration, I get undefined method 'pejis' for #<Chapter::ActiveRecord_Associations_CollectionProxy:0x0000000713d1a0>. I tried to also set as follow:
private
def set_scan
#chapter = Chapter.find_by(chapter_number: params[:id])
#scan = #chapter.scans.find_by(scan_number: params[:id])
end
But i get undefined method 'pejis' for nil:NilClass, which is weird because it doesn't return any error with predefined ids in the rails console.
As anyone an idea ?
Thank you in advance

So, after re-reading again and again my code, I simply needed to do the following:
def set_peji
#chapter = Chapter.find_by(chapter_number: params[:chapter_id])
#peji = #chapter.pejis.find_by(scan_number: params[:id])
end
So I had to remove #manga since it's not concerned anymore, then to set the scan's chapter_id as being the chapter's number.

Related

Got ForbiddenAttributesError when inserting an object with association

I ask you a little help as I'm starting with Ruby on Rails with a problem that is still bothering me after searching docs and forums.
The problem raises when trying to insert an object of a class that has an association of type "belongs to" with another class.
In this situation, after submitting in the "new" form, Rails gives me a ForbiddenAttributesError in this line of Enterprise controller :
#enterprise = #country.enterprises.build(params[:enterprise])
I don't know how it gives me that error since I'm sending all parameters from the view , and specified all parameters as white-listed in Enterprise class:
controller/enterprises_controller.rb
def new
#country = Country.find(params[:country_id])
#enterprise = #country.enterprises.build
end
def create
#country = Country.find(params[:country_id])
#enterprise = #country.enterprises.build(params[:enterprise])
if #enterprise.save
redirect_to country_enterprise_url(#country,#enterprise)
else
render :action => 'new'
end
end
private
def enterprise_params
params.require(:enterprise).permit(:param1,:param2,:param3)
end
Thanks in advance.
You are creating a 'permission' private action for permitting params, but not using it when creating instance..
instead of :
#enterprise = #country.enterprises.build(params[:enterprise])
write :
#enterprise = #country.enterprises.build(enterprise_params)
meaning: the name of the action
EDIT: Hence - it's not going through the params.require.permit validation
Please change the line to:
#enterprise = #country.enterprises.build(enterprise_params)

Show curent user's members based on user_id (Index View)

I have a user_id column. Instead of calling for all members how can I call up members based on current user's and user_id?
This is my controller, I tried changing .all to user_id or current_user.id plus many variations based on examples. Still can't get it. I also have no models (using authrocket). The create action also works and inserts the user_id, I have a def current_user at the bottom.
class Members::MainsController < ApplicationController
# Member Profile List
def index
#members_mains.user_id = current_user.id
#members_mains = Members::Main.all
end
private
# Common Callbacks
def set_members_main
#members_main = Members::Main.find(params[:id])
end
# White List
def members_main_params
params.require(:members_main).permit(:mfirstname, :mlastname, :mtitle, :memail, :mphone, :mnotes, :smfacebook, :smtwitter, :smlinkedin, :user_id)
end
end
If I got it right, your index action should be something like this:
# Member Profile List
def index
#current_member = Members::Main.find(current_user.id)
end
Do you intend to show a list of profiles for all members?
If not, your index action can simply be removed. If so, you wouldn't normally filter on a user_id at all for that action and you can remove that line.
To load a member profile for a specific user_id, try a show action something like this:
def show
#members_main = Members::Main.find_by(user_id: params[:id])
end
That will load a member profile based on the :id from the URL.
If you want to just show the current user's own profile instead, use current_user.id which will give you the AuthRocket user's ID.
def show
#members_main = Members::Main.find_by(user_id: current_user.id)
end
In either case, you may need to remove :show from the set_members_main callback.
Lastly, you probably want to remove :user_id from members_main_params so that users can't modify the AuthRocket user_id. You only want to control that directly (as you already are in the create action).
Hopefully that's clear enough to get you on your way, but I could be off a bit based on what functionality you actually intend for index and show.

Undefined method in controller - rails

I have a controller called blogger:
class BloggerController < ApplicationController
def home
end
def favoritePosts
#blogger = current_blogger
#favorites = #blogger.favorite_posts
end
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.similar_posts
end
end
And in the Blogger model i have a method:
def similar_posts
title_keywords = Post.body.split(' ')
Post.all.sort do |post1, post2|
post1_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection = post2.body.split(' ') & title_keywords
post2_title_intersection.length <=> post1_title_intersection.length
end
end
When i run the server its gives me an error:
undefined method `similar_posts' for #<Post::ActiveRecord_Relation:0x007fa365029760>
After searching on stackoverflow i tried def self.similar_postsbut it still gives the same error message. I also tried new in the controller like this #suggestedPosts = posts.new.similar_posts which still gives me the same error.
Any suggestions on how to overcome this?
You have 2 issues happening at the same time. The first is that you're using posts in your call, when you should be using something more like post.blogger. The specific object depends on what your intent actually is.
The second issue is that you're making the call to similar_posts on the association, not on an individual record. This can be resolved with a call to each on the association.
So, putting those together and looking at what you might have meant, I think that you might have intended this as your suggestedPosts method:
def suggestedPosts
posts = Post.all
#suggestedPosts = posts.map {|post| post.blogger.similar_posts }
end
I also changed the name of #suggestedDevelopers to #suggestedPosts, because I don't think that you meant 'developers' in this case. This should give you something closer to what it appear you were trying for.

How to add new element to array via link_to method

I have Exercise and User model. User can share his exercises with each other through SharedExercise model. Exercise may be public or private, and users are allowed to add public exercises to their private exercises. I need to add simple link/button to do this, but have no idea how.
Im looking for something like:
def add
#exercise = Exercise.find(params[:id])
current_user.exercises << #exercise
end
but how to pass that to link/button?
In Exercises Controller You could get array of users who have already been assigned to this exercise and add current_user to this array with next updating of this exercise...
Something like that:
def add_user
#exercise = Exercise.includes(:user_ids).where(id: params[:id])
#user_ids = #exercise.user_ids
!#user_ids.index(params[:user][:id]) && #exercise.user_ids = #user_ids.push(params[:user][:id])
...
if #exercise.update_attributes(#user_ids)
redirect_to ...

Rails 4: How to filter an ActiveRecord::Relation based on the presence of some string within an array field?

I am expanding the sample application of Michael Hartl's Rails Tutorial, which you can find here http://ruby.railstutorial.org/chapters/. The objective of the tutorial is to create a twitter-like website, therefore some of the models are User, Micropost and Relationship, where the last one is intended to establish the relationships of follower and followed among the users (just like in twitter) and to define the logic for retrieveng microposts from the database according the user.
That being said, I want to expand the sample application adding the following functionality:
When writing a micropost, this can be retrieved either by all the user's followers by default or by specific followers whose user names are explicitly included in the content of the micropost, with each name preceded by # symbol.
Example:
User ExampleUser posted two microposts:
micropost_1 with content "hello world" will appear in the micropost feed of every follower.
micropost_2 with content "hello world #john #peter" will appear only in peter's and john's micropost feeds (as long as peter and john are the names of actual users that follow ExampleUser).
In order to achieve this objective, so far I have done the following:
1) I added the field "receivers" of type text to the Micropost model through the console lines:
rails g migration AddReceiverToMicropost receivers:text
rake db:migrate
And then I added the following line to the Micropost model
class Micropost < ActiveRecord::Base
serialize :receivers
This allows me to save an array in the receivers field thanks to the serialize functionality (for this I based in the following site: http://amberonrails.com/storing-arrays-in-a-database-field-w-rails-activerecord/)
Thus, I would be able to store a string array with the receivers' names for a given micropost.
2) Next, I tried to solve the problem of extracting the receivers' names from a micropost's content. So I went to the MicropostsController and created the following method:
private
def get_receivers(content)
receivers = []
i = 0
i0 = 0
while i < content.length do
i = content.index('#',i0)
if i.nil?
break
else
i0 = content.index(' ',i)
if i0.nil?
unless i + 1 == content.length
receivers << content[i+1..-1]
end
break
else
unless i + 1 == i0
receivers << content[i+1..i0-1]
end
end
end
end
receivers
end
and then I applied it withing the MicropostsController's create method:
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
#micropost.update(receivers: get_receivers(#micropost.content)) #this line uses the get_receivers method to set the receivers field
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
The line followed by the comment is the added one.
So far this works properly.
3) Finnaly I tried to update the method that retrieves all the micropost feed of a user (properly signed-in) in order to implement the new functionality. The method is a class method called from_users_followed_by(user), defined in the Micropost model class, and this is the original code (as it appears in the tutorial):
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
end
This method is invoked by the feed method of User class, here is the code:
class User < ActiveRecord::Base
.
.
.
def feed
Micropost.from_users_followed_by(self)
end
And finally, feed in turn is invoked within the home method of the StaticPagesController in response to a request of displaying the sites's homepage provided that a user is properly signed-in at the moment:
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
So, you can see that the original self.from_users_followed_by(user) method retrieves all the user's followed users' microposts plus his own microposts. But in order to add the receivers filter layer, I updated it to this new version:
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
microposts = where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
user_id: user.id)
microposts_filtered = []
microposts.each do |m|
if m.receivers.nil? or m.receivers.length == 0 or m.receivers.include? user.name
microposts_filtered << m
end
end
microposts_filtered
end
As you can see, my attempt was to manually filter the microposts of the microposts Relation returned by the where method and pass the approved ones into the array microposts_filtered. I thought this was going to work, but a problem arises in the StaticPagesController's home method in the line
#feed_items = current_user.feed.paginate(page: params[:page])
and this is that an array has no method called paginate, which is a method of ActiveRecord::Relation class. That's the reason for my title question: how can I add this receivers filter layer in the where method in order to keep the Relation as output, since an array does not allow pagination?
Sorry for the long exposition of the problem but I did it this way for the sake of understanding. I would like to know how I could solve this problem or if there are other better approaches to achieve the same results in a better fashion. Improvements for any part of the whole problem (such as a better method to get the user names from a micropost's content) are welcomed. Thanks in advance.

Resources