I was following rails tutorial on how to use CRUD but this tutorial was using Rails 3. But because Rails 4 dropped the attr_accessible method I can't get my database to work. I am trying to create a simple blog post with a database that has a :title and content field, how would I implement this in the
Class Post < ActiveRecord::Base file
Side question: Do you recommend any good tutorials where they create an app using rails (like a blog etc) I can follow.
Thanks you
In Rails 4 you typically permit parameters at the controller level rather than defining access control at the model level.
def create
#user = user.create user_params
end
private
def user_params
params.require(:user).permit(
:name,
:age,
:shoe_size
)
end
I recommend reading Michael Hartl's Rails Tutorial. It's free to read online, or worth every penny for the printed version.
Related
I am trying to follow a ruby on rails scaffold example.
I am using ruby version: 2.1.5 with rails version : 4.1.8
I have used this command:
rails generate scaffold User name:string email:string
This worked fine - I can run the example which shows crud functionality to my generated scaffold. The examples I have been following advise to look at the model file generated. The ones in the examples seemed to have a value called attr_accessible - but for me this was not generated - I do not know why - it seems to be quite useful so you can easily see what is inside your model? My model looks like this:
class User < ActiveRecord::Base
end
I altered it to look like this :
class User < ActiveRecord::Base
attr_accessible :name, :email
validates :name, :presence=>true
end
and when I now visit localhost/users I get the error:
Can somebody please tell me how a generated model can be created with this attr_accessible line, and how I can add an example of validation to the model.
Rails 4 doesn't use attr_accessible; it uses Strong Parameters.
They both serve as a guard for mass assignment of params, often times used during form submissions.
The scaffold doesn't support automatically setting strong params as far as I'm aware, in part because people implement strong params white listing very differently.
A couple more links on Strong Params
How is attr_accessible used in Rails 4?
https://github.com/rails/strong_parameters
https://github.com/elabs/pundit#strong-parameters <= I strongly recommend this gem
To me this suggests whatever guide you're following is out of date.
I think the problem is that the scaffolding that you have used is not compatible with how Rails works in later versions. In earlier versions of Rails, attr_accessible was used for preventing security problems related to mass assignment. In later versions, the countermeasure changed and moved to the controller instead of the model.
If you still want to use the attr_accessible macro, you can add gem 'protected_attributes' to your Gemfile and install with bundler.
You shouldn't add them in the model.
The stuff you wanna access goes into the controller, like
def index
#users = User.all
end
def show
#user = User.find(params[id])
end
...
private
def user_params
# It's mandatory to specify the nested attributes that should be whitelisted.
# If you use `permit` with just the key that points to the nested attributes hash,
# it will return an empty hash.
params.require(:user).permit(:name, :mail)
end
so you can use them afterwards in your views.
e.g. in app/views/users/show...
<h1>#user.name</h1>
<p>#user.email</p>
I am very new to rails, but not so much to web development. I am currently working through teamtreehouse's Build a Simple Rails application and they are using Rails 3, whereas I am using rails 4.
In the status.rb which allows the users to post a status I have the following class:
class Status < ActiveRecord::Base
attr_accessible :content, :user_id
belongs_to :user
end
I appreciate that attr_accessible has been removed from rails 4 and now using params, but any reading I do, it requires the class name to change. Does anybody have any ideas on how I can make this work?
Thanks
You remove this line from the model.
attr_accessible :content, :user_id
Then in the controller you add a method to white list the parameters that can be mass-assigned.
def status_params
params.require(:status).permit(:content, :user_id)
end
And you use that to create a new Status
def create
Status.create(status_params)
end
More in the docs http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
As you said in rails 4 attr_accessible is removed and we use strong params. To make above code work in rails 4 you'll need to make a private method status_params in your status_controller and then while creating a status or updating a status you can pass that method in params like this:
class PeopleController < ActionController::Base
def create
#status = Status.new(status_params)
#status.save
end
private
def status_params
params.require(:status).permit(:content, :user_id)
end
end
We are not changing any class here, rails 4 has simply moved the attribute accessible logic to controllers from the model. For more details read about strong parameter
Another option is to add gem 'protected_attributes' to your projects gemfile and bundle install. 'protected_attributes' gem gives you the ability to use attr_accessible and attr_protected (like in rails 3 apps) in a rails 4 app.
However, I would recommend to focus on learning how to properly use strong_params as it is important and pretty straight forward. Refer to the Ruby-on-Rails guides for detailed explanations of strong_params and controllers in general.
Also, I'd recommend that you find and use newer tutorials that are on Rails 4, there are no shortage. There are many differences between Rails 3 and 4, some of which aren't apparent on the surface and especially not to a beginner. In terms of learning, the way to go is to learn how to build a rails app with one version of the framework and to do with resources/tutorials etc that are meant for that version of Rails. As a beginner, there is no good reason for unnecessarily adding the complexity of needing to account for the intricacies and differences of Rails 3 and 4.
Acutally i face some hard exercises in computer science (hard for me i think, haha).
We're doing some basic stuff with Ruby on Rails an i have to open a csv file to get additional information on my 'User' model which is a normal rails scaffold.
So at the moment i open the csv file in my users_controller.rb file and search for the right row an add them to an instance variable.
But i wonder if i can write a class that acts like an ActiveRecord Model. So i change the code to use ActiveModel. But as i read in some google results, ActiveModel can't make use of ActiveRecord like associations. But it would great to have them.
So i hope you can help me. How can i provide my model with ActiveRecors like associations?
Greetings
Melanie
It's absolutely right that the CSV file should be represented as a model, as it's data.
However, trying to incorporate Active Model sounds tricky and would almost certainly require a great deal of hacking or monkey patching.
Unless you really need associations to other models, I would create a standalone class (i.e. not inheriting from ActiveRecord::Base) in the models directory, and put the logic for parsing the CSV in there:
class User
attr_accessor :name, :email, ...
def initialize(name,email,...)
# set data
end
def self.find(param_for_search)
# Parse CSV file, find line you want
# return a User instance
self.new(name, email)
end
end
I don't know exactly how your system works, but this way you can make it behave in a similar way to Active Model stuff. You can add similar class methods and each instance method represents a CSV file row.
Every time , when you are creating your own model , it is inheritance of ActiveRecord :
class Project < ActiveRecord::Base
attr_accessible :content, :name, :user
end
Then you can tell your model to have many (let's say) Project's Tasks , which creates an association . Please , provide an example of your app's logic.
Here is a quote from RailsCasts.com :
"In Rails 3 the non-database functionality of Active Record is extracted out into Active Model. This allows you to cleanly add validations and other features to tableless models."
There is also a nice description how to add functionality in you model by adding modules .
I understand, that using ActiveRecord to use an non database source is difficult, but i think it would be vewy charming if i could write something like this:
user.worktimes.first.value
in my view and get the information like it is a database table. I visit railscast.com an i found a episode where this ist discussed. But i would like to digg deeper in this. Are there any further ressources i could read?
As i understand, ActiveModel does not support associations? I wonder why associations wasn't moved to ActiveModel as it is a very useful thing. :)
So here is my code, that i was working on:
User-Model:
class User < ActiveRecord::Base
attr_accessible :department_id, :name
belongs_to :department
end
Department-Model:
class Department < ActiveRecord::Base
attr_accessible :name
has_many :users
end
And here is my CSV Model, that i created:
class Worktime
attr_accessor :user_id,:date,:value
def initialize(params)
dir = Rails.root.join('app', 'models', 'worktimes.csv').to_s
source = File.open(dir,'r')
while(line=source.gets)
data = line.split(';')
if data[0] = params[:user_id] && data[1] = params[:date]
#value = data[2]
end
end
end
end
I am very thankful for your help as its my first time using rails.
I am using the gem postmarkdown to create a blog in RoR. The Post model in the gem is not backed by a database (it uses ActiveModel). How would I go about relating a Comment model to the Post model for a blog that does not utilize a database for the blog posts?
For example, with a typical blog backed by an ActiveRecord database, I could set up the relations (such as)
class Post < ActiveRecord::Base
has_many :comments
However, in this case, I don't know the best way to create a comment model.
If Post is an activemodel, you can't setup relations using methods in activerecord. You can check out the README at github. It doesn't have that functionality.
One way you could to is simply define your own methods inside Post model.
class Post
def comments
Comment.where(:post_id => id)
end
end
class Comment < ActiveRecord::Base
def post
Post.find_by_id(post_id)
end
end
Edit:
Ah, I just find a similar question, Ruby on Rails 3 (3.1) ActiveModel Associations (tableless nested models). You can check out that as well.
I have built a ruby on rails app that allows for users to track their workouts. I also allow them (like a blog) to create tags for their workouts. When users add tags to their workouts, they are assisted through auto_complete to help keep things organized.
As the site has grown in popularity I am getting a little bit of clutter/inconsistency because of capitalization. Is there a way to tell the app to only create tag.name's in uppercase or lowercase?
Try something like:
class Tag < AR::Base
before_save :downcase_name
private
def downcase_name
self.name.downcase!
end
end
Ruby has an upcase and downcase on the String class that will allow you to do either. Simply call before saving the data.
For example, if you are using the simple_auto_complete gem, you could do the following:
class BlogController < ApplicationController
autocomplete_for :post, :title do |items|
items.map {|x| x.upcase}
end
end
I can't test this right now, so forgive me if there are syntax errors.